HotPDF Notas de versão

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

  • A demo Delphi PreflightReport foi atualizada de console sample para uma ferramenta VCL GUI interativa para single-file preflight workflows.
  • A GUI agora cobre relatórios padrão text, JSON e HTML, senhas opcionais, profile INI files, presets integrados, single-file PDF/VT validation, embedded-report PDF output, report preview, status logging, automatic output naming e acesso rápido aos arquivos gerados.
  • O antigo comportamento de inicialização foi removido: quando nenhum command-line argument é fornecido, nenhum sample PDF nem report é criado automaticamente.

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 agora reutiliza o recurso de fonte Type 0 gerado por RegisterUnicodeTTF para a saída Unicode dos planos suplementares, de modo que o texto de página e os fluxos de aparência AcroForm compartilham o mesmo caminho de codificação CID interna.
  • A etapa de finalização compartilhada agora mantém a saída SMP em nível de página sincronizada por meio de FUnicodeUsedCps, /CIDToGIDMap, a entrada /W da fonte descendente e /ToUnicode, evitando o mapa SMP local de página mais antigo.

2026-05-24 Version 2.121.2

  • THPDFPage.UnicodeTextOut agora direciona caracteres Unicode do plano suplementar através do mapeamento de glifos do formato 12 registrado na fonte da página, quando RegisterUnicodeTTF carregou a fonte ativa. Emoticons e outros valores escalares U+10000 ou superiores são emitidos como um único glifo CID no fluxo de texto da página, em vez de dois CIDs de metades substitutas.
  • Os registros de mapa de caracteres `/ToUnicode` convertem os CIDs dos glifos SMP de volta para o par substituto UTF-16BE original, preservando a extração de texto e a acessibilidade, mantendo ao mesmo tempo o caminho de fonte de página existente `/CIDToGIDMap /Identity`.

2026-05-24 Version 2.121.1

  • RegisterUnicodeTTF: os fluxos de aparência do formulário AcroForm agora renderizam caracteres Unicode do plano suplementar, como emojis, usando um único CID interno, em vez de escrever um par substituto UTF-16 como dois CIDs Identity-H. O /CIDToGIDMap gerado mapeia esse CID para o glifo real, e o /ToUnicode o mapeia de volta para o par substituto UTF-16BE original para extração de texto.
  • A etapa de finalização da fonte Unicode atualiza /CIDToGIDMap, /W e /ToUnicode depois que todos os fluxos de aparência registram seus mapeamentos internos tardios de CID, garantindo que o subsetting TrueType e as aparências de formulário geradas usem o conjunto final de CIDs utilizados.

2026-05-23 Version 2.121.0

  • PDF 1.7 §12.6.4.13–15: as ações multimídia (Rendimento / Som / Vídeo) ganham três novos métodos auxiliares de botão: `AddPushButtonWithRenditionAction` para §12.6.4.13 (vincula uma anotação de tela a um MediaRendition + MediaClipData que descreve o clipe de áudio/vídeo e uma operação /OP de 0 a 4); `AddPushButtonWithSoundAction` para §12.6.4.14, com duas sobrecargas (caminho do arquivo ou carga útil raw `TBytes`), um registro `THPDFSoundParams` fornecido pelo chamador (Taxa de Amostragem / Canais / BitsPorAmostra / Codificação) e opcionais /Volume + /Repeat + /Synchronous; `AddPushButtonWithMovieAction` para §12.6.4.15 (refere-se a uma anotação de vídeo via /Annotation e seleciona /Operation Play / Stop / Pause / Resume).
  • AddScreenAnnotation e AddMovieAnnotation agora retornam o dicionário da anotação criada, permitindo que os chamadores o integrem na função auxiliar correspondente. A alteração da assinatura de procedure para function é compatível com a ABI do Delphi; os chamadores existentes que a invocam e descartam o resultado ainda compilam e geram arquivos PDF idênticos em bytes.
  • Implementação padrão: cada função auxilia emitindo as entradas obrigatórias especificadas, além dos campos opcionais mais comuns (Sound/Volume/Repeat/Synchronous; Rendition/JS). Os parâmetros opcionais de reprodução de mídia, parâmetros de tela de mídia, a renderização de seleção e o mix de som são intencionalmente omitidos — as configurações padrão do leitor cobrem 95% dos casos e as funções auxiliares permanecem mínimas.
  • PDF/A (todos os níveis) e PDF/X (todos os perfis) rejeitam as três ações multimídia na entrada do helper, exibindo um diagnóstico referenciado pela ISO (ISO 19005-1 §6.6.1 / ISO 19005-2 §6.5.1 / ISO 19005-3 §6.5.1 / ISO 15930). Os mecanismos de anotação existentes para `AddScreenAnnotation` / `AddSoundAnnotation` / `AddMovieAnnotation` permanecem ativos.
  • A ação Rendition associa o arquivo de metadados MediaClipData com as permissões de mídia /P /TF (TEMPACCESS) conforme a seção §13.2.6.1, Tabela 280, que representa o nível mínimo de permissão que permite ao leitor passar o conteúdo para os codecs de áudio/vídeo da plataforma.
  • Os fluxos de ação de som definem os campos opcionais para os valores especificados (Volume=1.0, Repeat=false, Synchronous=false) e os emitem apenas quando o chamador passa valores diferentes dos padrões, mantendo o dicionário de ação o mais compacto possível para o caso mais comum.
  • 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.
  • Verificado com as novas versões Win32 e Win64. Os testes `smoke_multimedia_actions` (que garantem a cobertura de todos os quatro tipos de ações e a cadeia de anotações de tela/vídeo) e `smoke_multimedia_actions_pdfa_pdfx` (que incluem 8 verificações abrangendo 3 ações × PDF/A + PDF/X) foram executados. O teste de regressão `smoke_button_actions` continua a passar após a refatoração da função `AddScreenAnnotation` e `AddMovieAnnotation`.

2026-05-23 Version 2.120.15

  • Correção: A função EndDoc serializava o grafo de objetos PDF antes que dois modificadores pós-compilação (o subsetor TrueType da versão v2.84.0 e o gerador automático de "abas" PDF/UA-1 §7.18.3 da versão v2.94.0) fossem executados, portanto, nenhuma dessas alterações era aplicada ao arquivo resultante. Documentos que utilizavam RegisterUnicodeTTF + AddTextField enviavam o arquivo de fonte completo (~1 MB em latim / ~14 MB em CJK) em vez do subset (~150 KB / ~500 KB), o prefixo de subset de seis letras "AAAAAA" estava ausente em /BaseFont, o fluxo /CIDSet no FontDescriptor estava ausente (o veraPDF sinalizava falhas em ISO 19005-1 §6.3.5 / -2 -3 §6.2.11), e os PDFs PDF/UA-1 que não continham a chave §7.18.3 /Tabs /S em páginas com anotações falhavam na regra 21-001 do Matterhorn e nas verificações PAC 3 "Tabs".
  • Ambos os modificadores agora são executados ANTES de SaveToStream / SaveToFile. Eles percorrem a lista de objetos indiretos e escrevem o PDF. A saída é idêntica em bytes à versão v2.120.14 para documentos que não registram um TTF Unicode nem habilitam PDFUACompliance; ambos os modificadores já eram operações sem efeito nessas situações, portanto, a reordenação altera apenas os documentos cuja saída na versão v2.120.14 estava silenciosamente corrompida.
  • Verificado com o teste Win32 smoke_unicode_ttf_subset (o subconjunto representa 33,6% do arquivo Arial no disco — economizados 676 KB — /BaseFont , prefixo UYENHH+ArialMT consistente em Type 0 / CIDFontType2 / FontDescriptor.FontName) e o teste Win32 smoke_pdfua_annot_structparents (/Tabs /S impresso no dicionário da página anotada, todas as cinco afirmações de estrutura de anotação §7.18.3 são verdes).

2026-05-23 Version 2.120.14

  • PDF/UA-1: implementada uma verificação rigorosa da estrutura e do papel (ISO 14289-1 §7.7 + ISO 32000-1 §14.7.3): com o PDFUACompliance habilitado, AddStructureElement agora rejeita qualquer papel "/S" que não seja um dos 41 tipos de estrutura padrão da Tabela 333 do PDF 1.7 §14.8.4 (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) nem um papel personalizado que o chamador tenha pré-registrado via AddStructRoleMap. A exceção de diagnóstico inclui a string do papel ofensivo, cita o PDF/UA-1 §7.7 / Tabela 333 e sugere a correção AddStructRoleMap. Um papel vazio também é rejeitado com uma mensagem específica. Sem essa verificação, papéis não conformes seriam silenciosamente adicionados à árvore de estrutura e causariam falhas "tipo de estrutura desconhecido" nas ferramentas veraPDF / PAC.
  • O novo recurso só é ativado quando PDFUACompliance é definido como True; as chamadas que não usam UA mantêm o comportamento anterior da função freeform-role, byte a byte. Todas as quatro sobrecargas de AddStructureElement (a versão base com 4 argumentos do tipo AnsiString, a sobrecarga com 6 argumentos para /Alt + /ActualText da versão v2.88.0, a sobrecarga com 7 argumentos para /ID da versão v2.95.0 e a sobrecarga do enum THPDFStandardStructureType da versão v2.119.41) convergem para o mesmo caminho, portanto, um único controle é suficiente. A sobrecarga do enum sempre passa um nome da Tabela 333 e, portanto, sempre passa na verificação; os usuários preferem essa opção para eliminar erros de digitação ou problemas de sensibilidade a maiúsculas e minúsculas (por exemplo, 'Para' vs 'P', 'Lbody' vs 'LBody') durante a compilação.
  • v2.119.41 já incluiu o enum THPDFStandardStructureType (41 nomes de especificação agrupados em 5 buckets de função 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), StandardStructureTypeToName(T) para pesquisa de enum para nome e IsStandardStructureType(Name) para validação do lado do chamador; v2.120.14 integra essas funcionalidades no ponto de entrada AddStructureElement, de modo que a verificação rigorosa seja automática. Um novo helper privado, _IsCustomRoleInRoleMap, percorre o array dinâmico FStructRoleMap com uma comparação de memória segura, correspondendo corretamente os nomes de função personalizados não ASCII em hosts CP_ACP=65001.

2026-05-23 Version 2.120.13

  • Correção: A versão 2.120.12 do HotPDF não conseguiu ser compilada no RAD Studio porque as duas sobrecargas de EnableShapingFeatureForSubset estavam localizadas dentro da seção publicada do THotPDF, o que o Delphi rejeita com o erro E2266 ("apenas um dos métodos sobrecarregados pode ser publicado"). Na versão 2.120.13, as duas sobrecargas são delimitadas por um par de seções públicas localizadas, para que a mesma API pública seja compilada corretamente no dcc32/dcc64; as propriedades e funções auxiliares circundantes permanecem publicadas, byte a byte. Não há alteração no comportamento em tempo de execução.

2026-05-23 Version 2.120.12

  • EnableShapingFeatureForSubset (conclusão da fase 8f): THotPDF.EnableShapingFeatureForSubset (FeatureTag) / the A sobrecarga da enumeração THPDFShapingFeature percorre cada pesquisa GSUB conectada ao recurso solicitado na versão v2.119.49. Define o estado de seleção de GSUBScript / GSUBLanguage, enumera cada GID substituto potencial em LookupType 1 (Single — delta sobre os glifos de Coverage + array substituteGlyphIDs do Formato 2), LookupType 2 (Multiple — Sequence.substituteGlyphIDs[]), LookupType 3 (Alternate — AlternateSet.alternateGlyphIDs[]), LookupType 4 (Ligature — Ligature.ligatureGlyph), LookupType 5 / 6 (Contextual / Chained Contextual — recursão nas pesquisas aninhadas SequenceLookupRecord com um limite de profundidade de 8), LookupType 7 (Extension — descompactação automática para o tipo de pesquisa efetivo) e LookupType 8 (Reverse Chained — substituteGlyphIDs[]), e combina os GIDs usando OR em FUnicodeExtraUsedGlyphs para que o subsetor EndDoc da versão v2.84.0 inclua todos os glifos que o recurso pode gerar no subconjunto da fonte incorporada. A fase 8f complementa o MarkUnicodeGlyphUsed por glifo da versão v2.119.50, com uma opção de ativação em lote no nível do recurso para clientes cujo pipeline de produção ativa um recurso universalmente.
  • A sobrecarga de enumeração direciona cada valor de THPDFShapingFeature para o conjunto de tags de recursos OpenType de 4 bytes correspondente: 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. A sobrecarga de string aceita qualquer tag de recurso OpenType de 4 bytes para um direcionamento mais preciso, além dos casos de enumeração incluídos. Aviso sobre o inchaço do subconjunto: habilitar recursos amplos (por exemplo, aalt Access All Alternates, alguns fontes incluem cada glifo em um script) pode incluir uma grande fração do conjunto de glifos da fonte no subconjunto, anulando o trabalho de redução de tamanho da versão 2.84.0 — os chamadores devem preferir Phase 9 MarkUnicodeGlyphUsed quando souberem os GIDs emitidos. Desativado por padrão / opt-in explícito. Fecha a última fase restante do GSUB Engine Roadmap Phase 8.
  • As regras de contrato defensivas correspondem à versão v2.119.50: nenhuma fonte é registrada, nenhuma tabela GSUB, tag não de 4 bytes, a funcionalidade está ausente no caminho (script, idioma), cadeia de pesquisa vazia — cada condição "não há nada a fazer" resulta em uma operação silenciosa (sem exceção). Chamadas repetidas são idempotentes (o mapa de bits é combinado por OR). A recursão de pesquisa aninhada nos formatos de subtabela 1/2 é adiada para uma revisão futura; o formato 3 é predominante em fontes do mundo real e está implementado. Os chamadores que precisam de cobertura contextual precisa dos formatos 1/2 podem usar a função per-glifo MarkUnicodeGlyphUsed.

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) registra uma entrada (substituição → sequência de origem). Casos de uso típicos: após a Substituição Múltipla (1 GID → N GIDs), a sequência de substituição é emitida e o mapeamento inverso é registrado para que o leitor/visualizador possa copiar/colar e retornar ao codeponto original; após a Substituição de Ligaduras (N GIDs → 1 GID de ligadura), a ligadura é emitida e o codeponto da ligadura é registrado, revertendo para a sequência de origem de N elementos (por exemplo, uma ligadura contextual CALT arbitrária reverte para seus codepontos componentes). ClearToUnicodeReverseMappings remove todos os registros feitos pelo chamador; ToUnicodeReverseMappingCount informa quantos mapeamentos estão pendentes.
  • EndDoc emite e anexa as entradas registradas pelo chamador como blocos adicionais de bfchar após o bloco interno de 35 entradas, divididos automaticamente em subblocos de 100 entradas por Adobe CMap e Especificação de Arquivos CIDFont (Nota Técnica nº 5014) §1.4.2, respeitando o limite do operador bfchar. Os pontos de código BMP emitem 4 dígitos hexadecimais; os pontos de código SMP emitem um par substituto UTF-16BE (8 dígitos hexadecimais) de acordo com a especificação do Adobe CMap. A ordem de registro é preservada, de modo que a semântica de "última escrita vence" dos bfchar dos leitores de PDF permite que os chamadores tenham um comportamento determinístico de substituição em caso de conflito com as 35 entradas internas (um chamador que registra um mapeamento personalizado para <FB01> "fi" substitui o padrão v2.119.65 no leitor). Os chamadores que nunca chamam RegisterToUnicodeReverseMapping mantêm o ToUnicode CMap idêntico ao baseline v2.120.10. SetFormUnicodeFontDict ('', nil) redefine o caminho e limpa o registro do chamador, para que o próximo registro de fonte Unicode comece do zero.

2026-05-23 Version 2.120.10

  • O módulo de formatação de texto de Myanmar (fase 8f.10) registra Myanmar (tag OpenType mymr) como o décimo e último script Indic no HotPDF, abrangendo tanto o bloco principal de Myanmar (U+1000-U+109F: Burmese, Mon, Sgaw Karen, Western Pwo, Shan, Rumai Palaung, Pa'o) quanto o bloco Extended-A (U+AA60-U+AA7F). Uma nova função ApplyMyanmarReorder realiza a reordenação na fase inicial e a função GetMyanmarCategory realiza a pesquisa de codepoint, sendo reutilizável através do dispatcher ApplyIndicReorder.
  • A estrutura silábica mais complexa do lote: Kinzi 3-CP O prefixo (U+1004 + U+103A + U+1039) no início da sílaba é detectado, reservado e emitido no início da saída, conforme R8; a vogal pre-base E (U+1031) é movida para o início da sílaba, conforme R10; quatro consoantes mediais Y / R / W / H (U+103B-U+103E) são coletadas e emitidas em ordem fixa Y -> R -> W -> H, conforme R9, independentemente da ordem na fonte.
  • ASAT (U+103A) e VIRAMA (U+1039) são tratados como virama para o processamento de consoantes empilhadas. DOT BELOW (U+1037) é renderizado abaixo da base; outros sinais de tom são renderizados acima. ANUSVARA (Bindu) é renderizado acima; VISARGA é renderizado após. Não há Repha.
  • Duas entradas de registro `IndicScripts` (bloco principal e bloco Extended-A) compartilham as mesmas funções de reordenação de Myanmar, portanto, as consoantes do bloco Extended-A e os sinais de tom Pa'o Karen são processados de forma transparente pelo dispatcher.
  • **Conclui o lote de 11 fases de modelagem de escritas indicas não Devanagari:** infraestrutura + 10 escritas indicas registradas — Devanagari, Bengali, Gujarati, Tamil, Telugu, Kannada, Malayalam, Sinhala (família Brahmic SIA), Khmer, Myanmar (Sudeste Asiático).
  • De acordo com a especificação Unicode 16.0 §16.3 (Myanmar) e a especificação de formatação Myanmar OpenType.

2026-05-23 Version 2.120.9

  • O formatador de texto Khmer (fase 8f.9): registra o Khmer (tag OpenType khmr, bloco Unicode U+1780-U+17FF) como a nona escrita Indic no HotPDF e a primeira da Sudeste Asiática. Um novo ApplyKhmerReorder realiza uma etapa de reordenação preliminar e o GetKhmerCategory faz a busca de pontos de código, ambos reutilizáveis através do ApplyIndicReorder.
  • Estrutura silábica independente (não o padrão Brahmic R1-R5 usado pelas fases 8f.1-8f.8): as vogais pré-base (E / AE / AI / OE / OO / AU) movem-se para o início da sílaba; os deslocadores de registro (MUUSIKATOAN, TRIISAP) e outros sinais acima da base são direcionados para o buffer acima da base; o Bindu (NIKAHIT) é renderizado acima; o Visarga (REAHMUK, YUUKALEAPINTU) é renderizado após.
  • COENG: tratamento de subscrito: cada COENG (U+17D2) + o par de consoantes forma um cluster de consoantes empilhadas que permanece no buffer base na ordem original, permitindo que os recursos GSUB 'pres' / 'blws' da fonte gerenciem o posicionamento do subscrito. O coeng aninhado é suportado.
  • No Repha: Os scripts Khmer não formam uma representação visual de "Repha", portanto, `Ra + COENG + Consoante` permanece na ordem original, em vez de ser rotacionado para o final da sílaba.
  • De acordo com a seção 16.4 da Unicode 16.0 (Khmer) e a especificação de formação OpenType para Khmer.

2026-05-23 Version 2.120.8

  • PAdES adbe-revocationInfoArchival CMS atributo assinado (Fase 9 do PAdES): emite o OID privado da Adobe 1.2.840.113583.1.1.8 que contém os valores de revogação CRL e OCSP dentro da assinatura CMS. O Adobe Acrobat prioriza este atributo para a verificação de revogação de assinatura, antes das pesquisas no dicionário DSS e das consultas de rede OCSP/CRL - fundamental para PDFs que podem ser validados offline e para a melhor interoperabilidade com o Adobe Acrobat.
  • Novos campos em `THPDFCMSSignOptions`:
    • AdobeCRLsDER: array of TBytes - cada entrada é um objeto `CertificateList` (RFC 5280) no formato DER, o mesmo formato dos fluxos `CRLs` do DSS.
    • AdobeOCSPsDER: array of TBytes - cada entrada é uma sequência `BasicOCSPResponse` (RFC 6960 §4.2.1) no formato DER. Observe: *não* é o wrapper `OCSPResponse` externo; os chamadores que possuem respostas OCSP completas devem primeiro descompactar a cadeia de bytes `responseBytes.response` para extrair a sequência `BasicOCSPResponse`.
  • Ativação: atributo emitido quando pelo menos um dos dois arrays não estiver vazio. O padrão, que é um array vazio (ambos os arrays), mantém a estabilidade no nível de bytes da versão v2.120.7.
  • ASN.1 DER de acordo com a especificação da Adobe: RevocationInfoArchival ::= SEQUENCE { crl [0] EXPLICIT SEQUENCE OF CRL OPTIONAL, ocsp [1] EXPLICIT SEQUENCE OF BasicOCSPResponse OPTIONAL, otherRevInfo [2] EXPLICIT SEQUENCE OF OtherRevInfo OPTIONAL }. Os campos [0] e [1] são usados pelo HotPDF; [2] (otherRevInfo para sistemas de revogação não X.509) permanece fora do escopo.
  • Formato do fio (ambos os ramos preenchidos): 30 A0 30 <...> A1 30 <...>
  • **Compatível com o dicionário DSS:** este atributo é *paralelo* (e não um substituto para) o dicionário PAdES-B-LT DSS (no nível do catálogo, `/DSS /Certs /OCSPs /CRLs /VRI`, introduzido na v2.110.0). Validadores PAdES rigorosos (EU DSS, mTOM) tendem a reconhecer o DSS; o Adobe Acrobat reconhece `adbe-revocationInfoArchival`. Para máxima interoperabilidade, preencha ambas as camadas com os mesmos bytes CRL/OCSP através de AddPAdESDSSCRL / AddPAdESDSSOCSP e `AdobeCRLsDER` / `AdobeOCSPsDER`.
  • O wrapper `HPDFCMSBuildSignedData` com 4 argumentos define os novos campos como zero, garantindo que os pacotes CMS legados permaneçam idênticos em termos de bytes.
  • De acordo com a referência de PDF da Adobe Acrobat + RFC 5280 (CRL) + RFC 6960 (OCSP).

2026-05-23 Version 2.120.7

  • PAdES content-time-stamp assinado por CMS atributo (Fase 8 do PAdES): emite 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) contendo um token de carimbo de tempo (TimeStampToken) pré-assinado, de acordo com o RFC 3161, que comprova que o conteúdo do documento existia no momento reivindicado pela TSA (Trusted Timestamping Authority) *antes* de o signatário assinar o documento. Diferente de signature-time-stamp (atributo não assinado da Fase 4, aplicado após a assinatura).
  • Novo campo `THPDFCMSSignOptions`. `GetContentTimeStamp: THPDFCMSTimestampCallback`. Design espelhado do `GetSignatureTimeStamp` da versão v2.120.3. O HotPDF invoca o callback com o hash SHA-256 do documento (o mesmo hash que o atributo `messageDigest` assinado contém) e incorpora o TimeStampToken DER retornado como o valor do atributo content-time-stamp dentro de SignedAttributes.
  • `nil` padrão = nenhuma marca de tempo de conteúdo emitida. Os chamadores que desejam isso devem atribuir um bloco de código que implementa um TSA (Timestamping Service) conforme definido na RFC 3161 sobre HTTP. Um valor vazio retornado por `TBytes` significa que a operação é ignorada silenciosamente (degradação graciosa quando o TSA não está acessível).
  • **Pontos finais da TSA gratuitos** (sem necessidade de assinatura) para casos de uso não qualificados: http://timestamp.digicert.com, http://timestamp.sectigo.com, http://timestamp.globalsign.com/tsa/r6advanced1, https://freetsa.org/tsr, http://timestamp.apple.com/ts01. Cenários qualificados eIDAS requerem uma QTSA comercial; a assinatura para fins não legais funciona com os pontos finais gratuitos (com limite de taxa, mas adequados para fluxos de trabalho típicos).
  • Callback contract: invocado uma vez por operação de assinatura, *antes* que os atributos assinados sejam finalizados. Os bytes TST se tornam parte do que é assinado, portanto, a assinatura em si cobre o carimbo de data/hora do conteúdo – é por isso que é um atributo assinado (em vez de um carimbo de data/hora da assinatura, que não é assinado e reside em unsignedAttrs após a assinatura).
  • O wrapper `HPDFCMSBuildSignedData` com 4 argumentos define `GetContentTimeStamp:=nil` para que os pacotes CMS legados permaneçam idênticos em termos de bytes.
  • Responsabilidade do chamador: Os espaços reservados PAdES precisam de `ContentsBytes` dimensionados para a assinatura, mais o carimbo de tempo do conteúdo (TST) (~4-8 KB, normalmente). Para fluxos de trabalho B-T que combinam o carimbo de tempo do conteúdo e o carimbo de tempo da assinatura, inclua ambos os TSTs. O valor padrão de 16 KB em `AddPAdESSignatureField(Profile='B-T')` geralmente é suficiente para a maioria das combinações.
  • De acordo com 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

  • Atributos de assinatura PAdES v2: o campo opcional `signedAssertions [2]` permite que o signatário anexe declarações assinadas identificadas por OID (declarações SAML 2.0, tokens JWT compactos, credenciais OAuth, tokens de atestado específicos da organização) dentro da assinatura CMS.
  • Novo registro `THPDFSignedAssertion`: `SignedAssertionID` (OID pontilhado que identifica o tipo de asserção) mais `AssertionBody: TBytes` (bytes ANY pré-codificados que o esquema do OID define - normalmente uma STRING DE OCTETES que envolve o XML SAML ou a forma compacta JWT). Um `AssertionBody` vazio omite o campo ANY, deixando apenas o `signedAssertionID` (válido de acordo com a especificação para asserções do tipo booleano registradas por OID).
  • Novo campo `THPDFCMSSignOptions`: `SignedAssertions: array de THPDFSignedAssertion`. Várias asserções são suportadas; o HotPDF envolve a sequência em `[2] EXPLICIT` (tag `0xA2`).
  • O atributo `SignerAttributeV2` agora aciona a condição quando qualquer um dos três campos opcionais é preenchido. Preencher todos os três campos resulta em: `SignerAttributeV2 SEQUENCE { [0] claimed..., [1] certified..., [2] signedAssertions... } na ordem dos campos especificados.
  • De acordo com a norma ASN.1 da ETSI EN 319 122-1 §5.2.6: SignedAssertion ::= SEQUENCE { signedAssertionID OBJECT IDENTIFIER, signedAssertion ANY DEFINED BY signedAssertionID OPTIONAL }. Estrutura de dados para uma única asserção com corpo: A2 30 30 06 .
  • Reutiliza `CMSEncodeOIDFromString` (v2.120.1) para a codificação de OID, aceitando qualquer OID em notação pontilhada.
  • O wrapper `HPDFCMSBuildSignedData` de 4 argumentos define como zero o novo campo, garantindo que os pacotes CMS legados permaneçam idênticos em termos de bytes.
  • 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.
  • De acordo com a norma ETSI EN 319 122-1 V1.2.1 §5.2.6 e o ANEXO A.1.

2026-05-23 Version 2.120.5

  • O branch `certifiedAttributesV2` da ferramenta PAdES signer-attributes-v2 **(PAdES Fase 6):** emite certificados de atributos X.509 (RFC 5755) dentro da sequência `SignerAttributeV2`, juntamente com ou em substituição aos atributos `claimedAttributes` da versão v2.120.4. Isso permite que o signatário anexe certificados de função de Autoridade de Atributos (AA) que fornecem suporte criptográfico à identidade/capacidade declarada.
  • Novo campo `THPDFCMSSignOptions`: `CertifiedAttributeCertsDER: array de TBytes`. Cada elemento é o certificado `AttributeCertificate` (RFC 5755) codificado em DER completo que o chamador recebeu da Autoridade de Assinatura (AA). O HotPDF os emite exatamente dentro de uma sequência `CertifiedAttributesV2` envolvida por `[1] EXPLICIT` (tag `0xA1`).
  • O atributo `signer-attributes-v2` é agora emitido quando qualquer um dos seguintes é diferente de vazio: ClaimedRoles ou CertifiedAttributeCertsDER. Quando ambos são preenchidos, uma sequência `SignerAttributeV2` é criada, contendo `[0]` e `[1]` na ordem especificada.
  • Formato ASN.1 DER (apenas para CertifiedAttributesV2): A1 30 onde cada ACn é a sequência verbatim fornecida pelo chamador, conforme especificado no RFC 5755 AttributeCertificate SEQUENCE. A escolha entre AttributeCertificate e OtherAttributeCertificate é determinada pela entrada DER do chamador (ambas as alternativas começam com a tag SEQUENCE 0x30; o HotPDF não faz introspecção).
  • O wrapper `HPDFCMSBuildSignedData` de 4 argumentos redefine o novo campo para que os pacotes CMS legados permaneçam idênticos em bytes à versão v2.119.27.
  • Escopo: as asserções assinadas [2] (tokens SAML / JWT / OID arbitrários) ainda estão pendentes e serão implementadas na próxima fase.
  • De acordo com ETSI EN 319 122-1 V1.2.1 §5.2.6 + ANEXO A.1 + RFC 5755.

2026-05-23 Version 2.120.4

  • PAdES signer-attributes-v2 assinado por CMS, atributo (PAdES Fase 5): emite id-aa-ets-signerAttrV2 (OID 0.4.0.19122.1.1, ETSI EN 319 122-1 §5.2.6), permitindo que o signatário declare os papéis reivindicados (por exemplo, "Diretor Financeiro", "Representante Autorizado") dentro do pacote CMS. Substitui a versão v1 signerAttr (RFC 5126 §5.10) para novas assinaturas.
  • Novo registro `THPDFClaimedRole`: `RoleOID` (tipo de atributo OID em notação pontilhada, geralmente um OID de função organizacional ou `1.3.6.1.5.5.7.20.1` id-id-aa-PERMrole) + `RoleValue` (string UTF-8 contendo o rótulo da função legível).
  • Novo campo `THPDFCMSSignOptions`. `ClaimedRoles: array de THPDFClaimedRole`. Vários roles são suportados; cada um se torna um `Attribute` dentro da sequência `claimedAttributes [0]`. Um array vazio (padrão) suprime o atributo, mantendo a estabilidade no nível de bytes a partir da versão v2.120.3 para os clientes que não optaram por essa funcionalidade.
  • ASN.1 DER conforme ETSI EN 319 122-1 §5.2.6 + ANEXO A.1 (módulo DEFINITIONS EXPLICIT TAGS): SignerAttributeV2 SEQUENCE { [0] EXPLICIT ClaimedAttributes } onde ClaimedAttributes ::= SEQUENCE OF Attribute. Cada função serializa como Attribute { type OID, values SET OF UTF8String }. A tag EXPLICIT significa que 0xA0 envolve literalmente a SEQUENCE OF interna (a tag interna 0x30 é preservada).
  • OID codificado manualmente: 04 00 81 95 32 01 01 (arco 0.4.0.19122.1.1; base-128 continuação em 19122 → 0x81 0x95 0x32). Valores personalizados futuros podem usar `CMSEncodeOIDFromString` a partir da versão v2.120.1.
  • **Escopo:** Apenas claimedAttributes [0] foi implementado nesta fase. certifiedAttributesV2 [1] (certificados de atributos X.509 conforme RFC 5755) e signedAssertions [2] (tokens no estilo SAML/JWT) exigem infraestrutura adicional e estão fora do escopo até que haja uma demanda concreta.
  • 4-arg `HPDFCMSBuildSignedData` wrapper zera o comprimento de `ClaimedRoles` para que os pacotes CMS legados permaneçam idênticos em bytes à versão v2.119.27.
  • De acordo com ETSI EN 319 122-1 V1.2.1 §5.2.6 + EN 319 142-1 V1.2.1, §6.3, Tabela 1, linha signer-attributes-v2 (OPCIONAL, 0 ou 1).

2026-05-23 Version 2.120.3

  • PAdES timestamp de assinatura CMS não assinado atributo (Fase 4 do PAdES): emite id-aa-signatureTimeStampToken (OID 1.2.840.113549.1.9.16.2.14, RFC 3161 §6 + ETSI EN 319 122-1 §5.3) dentro do conjunto [1] IMPLICIT unsignedAttrs do SignerInfo. Fornece o caminho do timestamp de assinatura para o serviço de tempo confiável PAdES-B-T (Tabela 1: B-T *deve ser fornecido* através do timestamp de assinatura *ou* do timestamp do documento).
  • Novo tipo de método anônimo `THPDFCMSTimestampCallback`: `reference to function(const SigValueSHA256: TBytes): TBytes`. O HotPDF invoca o callback com o hash SHA-256 de `SignerInfo.signatureValue` (a "messageImprint" do RFC 3161, conforme a seção 2.4.2) e incorpora o TimeStampToken DER retornado como o valor do atributo.
  • Novo campo `THPDFCMSSignOptions`: `GetSignatureTimeStamp`. O valor padrão é `nil`, o que significa que nenhum timestamp é usado; as chamadas de PAdES-B-T atribuem um bloco de código que controla a interação HTTP/RFC 3161 com o TSA e retorna os bytes do TST. Se forem retornados bytes T vazios, a operação é ignorada sem erro (por exemplo, o TSA pode estar inacessível, mas a assinatura ainda deve ser gerada).
  • As funcionalidades de rede/autenticação/gerenciamento de contas TSA permanecem no código do chamador; HotPDF apenas passa o resultado para o atributo `unsignedAttrs`. Isso se encaixa naturalmente com o tamanho do espaço reservado existente `AddPAdESSignatureField(Profile='B-T', ContentsBytes >= 16384)`.
  • ASN.1 wire: A sequência SignerInfo agora opcionalmente carrega um `[1] IMPLICIT SET OF Attribute` (tag `0xA1`) que contém um atributo `signature-time-stamp` cujo valor é o `TimeStampToken ContentInfo` fornecido pelo chamador, exatamente como está.
  • Conjuntos de wrappers `HPDFCMSBuildSignedData` com 4 argumentos definem `GetSignatureTimeStamp:=nil` para que os pacotes CMS legados permaneçam idênticos em termos de bytes.
  • De acordo com o RFC 3161 §6 + ETSI EN 319 122-1 §5.3 + EN 319 142-1 V1.2.1 §6.3 Tabela 1, nota q (B-T pode usar tanto a marcação de tempo da assinatura quanto a marcação de tempo do documento para fins de confiança).

2026-05-23 Version 2.120.2

  • PAdES commitment-type-indication CMS Suporte a atributos assinados (PAdES Fase 3): emite o atributo 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), declarando o tipo de compromisso que o signatário assume através da assinatura (por exemplo, prova de origem / recebimento / entrega / remetente / aprovação / criação).
  • Novo enum `THPDFCommitmentType`: `ctNone` (padrão, suprime o atributo), `ctProofOfOrigin`, `ctProofOfReceipt`, `ctProofOfDelivery`, `ctProofOfSender`, `ctProofOfApproval`, `ctProofOfCreation` (seis OIDs padrão `id-cti-ets-*` do RFC 5126 §5.11.1, arc `1.2.840.113549.1.9.16.6.{1..6}`), e `ctCustom` (o chamador fornece um OID arbitrário através do novo campo `CommitmentTypeOID`).
  • Ativação: ocorre sempre que o `THPDFCMSSignOptions.CommitmentType` não é `ctNone`. O valor padrão vazio mantém a estabilidade no nível de bytes na versão v2.120.1 para os chamadores que não optaram por essa funcionalidade.
  • **Responsabilidade do chamador (PAdES Parte 1 §6.3 Tabela 1, nota d):** ao emitir a indicação do tipo de compromisso, a entrada `/Reason` no dicionário de assinatura deve estar ausente (exclusão mútua). O HPDFCMS não verifica o estado do dicionário de assinatura; o chamador escolhe uma das opções através de `AddPAdESSignatureField(Reason='', ...)` e `CommitmentType`, ou deixando `CommitmentType=ctNone` e fornecendo `Reason`.
  • Estrutura ASN.1 DER: CommitmentTypeIndication SEQUENCE { commitmentTypeId OBJECT IDENTIFIER }. O CommitmentTypeQualifier (RFC 5126 §5.11.2) é omitido, pois os seis OIDs padrão id-cti-ets-* não definem qualificadores. Compromissos personalizados que necessitam de qualificadores podem ser estendidos através de uma função auxiliar.
  • O wrapper `HPDFCMSBuildSignedData` de 4 argumentos define como zero o novo campo `CommitmentType`, para que os pacotes CMS legados permaneçam idênticos em termos de bytes à versão v2.119.27.
  • De acordo com ETSI EN 319 122-1 §5.2.3 + RFC 5126 §5.11 + ETSI EN 319 142-1 V1.2.1 §6.3 Tabela 1, nota d.

2026-05-23 Version 2.120.1

  • PAdES signature-policy-identifier CMS Suporte a atributos assinados (Fase 2 do PAdES): emite o atributo 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) que declara a política de assinatura sob a qual a assinatura foi produzida. Obrigatório para PAdES-E-EPES (Parte 2 V1.2.1 §5.4 Tabela 2: *deve estar presente*); pode estar presente em todos os outros níveis do PAdES.
  • Novos campos no registro `THPDFCMSSignOptions`: `SignaturePolicyOID` (string OID pontuado do documento de política), `SignaturePolicyHash` (soma de verificação do documento de política), `SignaturePolicyHashAlgOID` (OID do algoritmo de soma de verificação, padrão para SHA-256 quando vazio) e `SignaturePolicyURI` (qualificador SPuri opcional conforme RFC 5126 §5.8.1, OID `1.2.840.113549.1.9.16.5.1`, que aponta para a URL do documento de política).
  • Ativação: o atributo de política é emitido apenas quando tanto `SignaturePolicyOID` quanto `SignaturePolicyHash` são preenchidos pelo chamador. Valores padrão vazios significam que o atributo é suprimido; os signatários de nível básico permanecem estáveis no nível de byte com a saída da versão v2.120.0.
  • A nova função auxiliar `CMSEncodeOIDFromString` codifica OIDs em notação pontilhada para DER, de acordo com X.690 §8.19 (os dois primeiros segmentos são combinados como `40*arc1 + arc2`, e os segmentos subsequentes usam base-128 com bits de continuação). Os OIDs de política são específicos de cada empresa, portanto, o produtor não pode codificá-los como literais de byte.
  • Estrutura ASN.1 DER: SignaturePolicyId SEQUENCE { sigPolicyId OBJECT IDENTIFIER, sigPolicyHash OtherHashAlgAndValue [, sigPolicyQualifiers SEQUENCE OF SigPolicyQualifierInfo] }. O qualificador SPuri envolve a URL como IA5String (tag 0x16) dentro de um SigPolicyQualifierInfo.
  • Compatibilidade: as chamadas da versão v2.120.0 que não preencheram os novos campos de política produzem resultados idênticos em termos de bytes. O wrapper `HPDFCMSBuildSignedData` com 4 argumentos define os novos campos como zero, garantindo que os pacotes CMS legados permaneçam inalterados.
  • De acordo com ETSI EN 319 122-1 §5.2.9 + ETSI EN 319 142-2 V1.2.1 §5.4 Tabela 2 + RFC 5126 §5.8.

2026-05-23 Version 2.120.0

  • Conformidade com o atributo CMS de referência PAdES (Fase 1 do PAdES): `SignPDFWithPFX` agora emite o atributo assinado **ESS signing-certificate-v2** (RFC 5035 / OID `1.2.840.113549.1.9.16.2.47`) por padrão, protegendo a identidade do certificado de assinatura contra ataques de substituição. A tabela 1 da seção 6.3 do ETSI EN 319 142-1 V1.2.1 lista isso como *deve ser fornecido* para todos os níveis de referência (B-B / B-T / B-LT / B-LTA).
  • A partir de agora, a funcionalidade PAdES padrão omite o atributo `signing-time` do CMS por padrão. A Tabela 1 exige que a cardinalidade seja 0 para os perfis padrão (o tempo de assinatura declarado é fornecido pela entrada ` /M` no dicionário de assinatura, conforme a nota g da Tabela 1). A versão anterior, v2.119.27, incluía `signing-time` independentemente do perfil, o que fazia com que verificadores PAdES rigorosos (como o EU DSS e o modo PAdES padrão do Adobe Acrobat) rejeitassem o documento.
  • Nova API pública: enumeração `THPDFPAdESLevel` (com 8 valores que abrangem os níveis B-B / B-T / B-LT / B-LTA, os níveis estendidos E-BES / E-EPES / E-LTV e o formato legado `adbe.pkcs7`), registro `THPDFCMSSignOptions` (nível + horário de assinatura + chaves de alternância para `signing-cert-v2` + carimbo de data/hora UTC), helper `HPDFCMSDefaultOptions(Level)` que retorna valores padrão compatíveis com a especificação para cada nível e construtor CMS orientado a opções `HPDFCMSBuildSignedDataEx`.
  • Compatibilidade retroativa: a assinatura HPDFCMSBuildSignedData com quatro argumentos da versão v2.119.27 é mantida como uma camada fina e gera uma saída idêntica em bytes (certificado de assinatura v2 ausente, horário de assinatura conforme solicitado). Os chamadores que calcularam o hash do pacote CMS da versão v2.119.27 nos testes continuam funcionando corretamente.
  • Alteração de comportamento na saída de PDFs assinados: qualquer chamada a `THotPDF.SignPDFWithPFX` com um espaço reservado PAdES (usando `AddPAdESSignatureField`, SubFilter `ETSI.CAdES.detached`) agora gera assinaturas que passam na validação básica PAdES. Para obter o conjunto de atributos legados v2.119.27, utilize diretamente `HPDFCMSBuildSignedDataEx` com `HPDFCMSDefaultOptions(palLegacy_adbePkcs7)`.
  • Estrutura ASN.1 DER conforme RFC 5035 §3: `SigningCertificateV2 SEQUENCE { certs SEQUENCE OF ESSCertIDv2 }` com o identificador de algoritmo SHA-256 omitido (regra DER de valor padrão X.690 §11.5), hash do certificado SHA-256, e `IssuerSerial` reutilizando a extração existente do emissor + número de série do `CMSExtractIssuerAndSerial`.
  • De acordo com a norma ETSI EN 319 142-1 V1.2.1 §6.3, Tabela 1, e o RFC 5035 §3.

2026-05-23 Version 2.119.77

  • Adicionado suporte para a escrita Sinhala (Fase 8f.8). O Sinhala ('sinh', U+0D80-U+0DFF) se torna a oitava escrita Indic registrada. Novos métodos `ApplySinhalaReorder` e `GetSinhalaCategory` foram adicionados ao THotPDF.
  • Recursos do Sinhala: possui Repha (Ra=U+0DBB + Halant=U+0DCA AL-LAKUNA); três matras pré-base (E=U+0DD9, EE=U+0DDA, AI=U+0DDB) — únicos por possuírem três matras pré-base; 3 matras divididas (U+0DDC O, U+0DDD OO, U+0DDE AU) com decomposição Unicode canônica; U+0DDD OO é composta por 3 partes (E + AA + AL-LAKUNA).
  • O dispatcher `ApplyIndicReorder` agora suporta Sinhala de forma transparente (o registro IndicScripts agora é um array de tamanho 0 a 7).
  • 21 novos testes DUnitX. No total, 187 testes foram executados e aprovados em Win32 + Win64.
  • De acordo com a especificação Unicode 16.0 §12.11 (Sinhala) e a especificação de formatação Sinhala do OpenType.

2026-05-23 Version 2.119.76

  • Adicionado o formador de Malayalam (Fase 8f.7). O Malayalam ('mlym', U+0D00-U+0D7F) torna-se o 7º script Indic registrado. Novos métodos `ApplyMalayalamReorder` e `GetMalayalamCategory` para `THotPDF`.
  • Recursos para Malayalam: inclui Repha (Ra=U+0D30 + Halant=U+0D4D, CHANDRAKKALA); I-matra (U+0D3F) é baseado no caractere posterior, como em Tamil (único em comparação com Devanagari/Bengali/Gujarati, que usam uma base anterior); pre-bases para E/EE/AI; 3 matras separadas (U+0D4A O / U+0D4B OO / U+0D4C AU) com decomposição canônica pre+post; letras chillu (U+0D54-U+0D56, U+0D7A-U+0D7F) e DOT REPH (U+0D4E) são classificadas como consoantes.
  • O dispatcher `ApplyIndicReorder` agora suporta Malayalam de forma transparente (o registro IndicScripts agora é um array de tamanho 0 a 6).
  • 21 novos testes DUnitX foram adicionados, incluindo cobertura para a categoria chillu/DOT-REPH. No total, 166 de 166 testes foram aprovados no Win32 + Win64.
  • De acordo com a seção 12.10 da especificação Unicode 16.0 (malaiala) e a especificação de formatação malaiala OpenType.

2026-05-23 Version 2.119.75

  • Adicionado suporte para a escrita Kannada (roteiro do motor GSUB, Fase 8f.6). Kannada ('knda', U+0C80-U+0CFF) torna-se a sexta escrita Indic registrada. Novos métodos públicos `ApplyKannadaReorder` e `GetKannadaCategory` foram adicionados em `THotPDF`.
  • Em Kannada, o caractere Repha (Ra=U+0CB0 + Halant=U+0CCD) é semelhante ao encontrado em Devanagari, Bengali, Gujarati e Telugu. Assim como em Telugu, Kannada não possui matras pré-base; cada matra em Kannada é acima da base, abaixo da base, após a base ou dividida.
  • Dividimos 5 matras usando a decomposição canônica do Unicode 16.0: U+0CC0 II → U+0CBF (superior) + U+0CD5 (posterior); U+0CC7 EE → U+0CC6 (superior) + U+0CD5 (posterior); U+0CC8 AI → U+0CC6 + U+0CD6 (ambos superiores); U+0CCA O → U+0CC6 (superior) + U+0CC2 (posterior); U+0CCB OO é composto por três partes: U+0CC6 (superior) + U+0CC2 (posterior) + U+0CD5 (posterior) — a primeira divisão de três partes é processada pela família de formadores Phase 8f.
  • Acima da linha de base (R3): I (U+0CBF), E (U+0CC6), AU (U+0CCC), marca de duração AI (U+0CD6). Abaixo da linha de base (R4): vogal R/RR (U+0CC3-U+0CC4), vogal L/LL (U+0CE2-U+0CE3). Abaixo da linha de base (R5): AA (U+0CBE), U/UU (U+0CC1-U+0CC2), marca de duração abaixo da linha de base (U+0CD5).
  • O dispatcher `ApplyIndicReorder` seleciona automaticamente o Kannada através do registro (agora array[0..5]).
  • Testes: 21 novos casos de teste DUnitX, incluindo todos os 5 casos de matra dividida, além de uma verificação dedicada de três partes para "OO". No total, 145 de 145 testes foram aprovados no Win32 e Win64.
  • De acordo com a seção 12.9 da Unicode 16.0 (Kannada) e a especificação de formação Kannada do OpenType.

2026-05-23 Version 2.119.74

  • Adicionado suporte para a escrita Telugu (roteiro do motor GSUB, Fase 8f.5). Telugu ('telu', U+0C00-U+0C7F) se torna a quinta escrita Indic registrada. Novos métodos públicos `ApplyTeluguReorder` e `GetTeluguCategory` foram adicionados em `THotPDF`.
  • Em Telugu, o caractere Repha (Ra=U+0C30 + Halant=U+0C4D) é semelhante ao encontrado em Devanagari, Bengali e Gujarati. Diferentemente de todos os scripts indicos anteriores, não existem "matras" (acentos) que se conectam diretamente à letra base; em vez disso, cada "matra" em Telugu está acima, abaixo ou dividida em relação à letra base.
  • Acima da linha base (R3): AA/I/II/E/EE/O/OO/AU, mais o sinal de duração. Abaixo da linha base (R4): U/UU/vogal R/RR (U+0C41-U+0C44), sinal de duração AI (U+0C56), vogal L/LL (U+0C62-U+0C63).
  • 1. A matra U+0C48 AI é dividida em U+0C46 (E acima da base) + U+0C56 (marca de comprimento AI abaixo da base) durante a reordenação.
  • O dispatcher `ApplyIndicReorder` seleciona automaticamente o idioma Telugu através do registro (agora array[0..4]).
  • Testes: 17 novos casos de teste DUnitX. No total, 124 testes de 124 foram aprovados no Win32 e Win64.
  • De acordo com a seção 12.8 da especificação Unicode 16.0 (Telugu) e a especificação de formação Telugu do OpenType.

2026-05-23 Version 2.119.73

  • Adicionado suporte para a escrita Tamil (GSUB engine roadmap Fase 8f.4). Tamil ('taml', U+0B80-U+0BFF) se torna a quarta escrita Indic registrada. Novos métodos públicos `ApplyTamilReorder` e `GetTamilCategory` foram adicionados em `THotPDF`.
  • As diferenças do tâmil em relação a outras escritas bráhmicas: NÃO possui Repha (o tâmil tradicionalmente não forma Repha visualmente); I-matra (U+0BBF) é pós-base, o que é único entre as escritas bráhmicas; II (U+0BC0) está acima da base; E/EE/AI (U+0BC6-U+0BC8) são pré-base; existem 3 matras divididas (U+0BCA O = U+0BC6+U+0BBE, U+0BCB OO = U+0BC7+U+0BBE, U+0BCC AU = U+0BC6+U+0BD7).
  • Em Tamil, o caractere Halant é chamado de PULLI, com o código U+0BCD. A função `ApplyIndicReorder` seleciona automaticamente o idioma Tamil através do registro (agora em um array de 0 a 3).
  • Testes: 20 novos casos de teste DUnitX. No total, 107 testes de 107 foram aprovados em Win32 + Win64.
  • De acordo com o Unicode 16.0 §12.7 (Tamil) e a especificação de modelagem Tamil do OpenType.

2026-05-23 Version 2.119.72

  • Adicionado suporte para a escrita Gujarati (GSUB engine roadmap Fase 8f.3). O Gujarati ('gujr', U+0A80-U+0AFF) torna-se a terceira escrita Indic registrada, após Devanagari e Bengali. Novos métodos públicos ApplyGujaratiReorder e GetGujaratiCategory em THotPDF.
  • Reorganize as regras: R1 Repha (Ra=U+0AB0 + Halant=U+0ACD), R2 pré-base (U+0ABF I), R3 acima da base (U+0AC5 CANDRA E, U+0AC7 E, U+0AC8 AI — observe que "acima da base" em Gujarati é como em Devanagari, e NÃO como em Bengali, que é "pré-base"), R4 abaixo da base (U+0AC1-U+0AC4, U+0AE2-U+0AE3), R5 pós-base (U+0ABE AA, U+0AC0 II, U+0AC9 CANDRA O, U+0ACB-U+0ACC O/AU). Sem divisões de matras.
  • O componente `ApplyIndicReorder` seleciona automaticamente o Gujarati através do registro `IndicScripts` (agora um array de índice 0 a 2). A integração `BuildUnicode*FieldContent` utiliza o conjunto `sfIndicShaping` para o Gujarati, sem alterações na integração.
  • Testes: 18 novos casos de teste DUnitX, incluindo cobertura acima da base para distinguir o tratamento de E/AI do Gujarati em relação ao do Bengali. No total, 87 de 87 testes foram aprovados no Win32 e Win64.
  • De acordo com a seção 12.6 da especificação Unicode 16.0 (Gujarati) e a especificação de formação Gujarati do OpenType.

2026-05-23 Version 2.119.71

  • Adicionado suporte para a escrita Bengali (roteiro do motor GSUB, Fase 8f.2). O Bengali ('beng', U+0980-U+09FF) torna-se a segunda escrita Indic registrada, após o Devanagari. Novos métodos públicos, ApplyBengaliReorder e GetBengaliCategory, foram adicionados ao THotPDF, espelhando a API do Devanagari da Fase 8e.
  • Regras de reordenação em Bengali: R1 Repha (Ra=U+09B0 + Halant=U+09CD), R2 matras de base (I=U+09BF, E=U+09C7, AI=U+09C8 — observe que E/AI são pre-base em Bengali, diferentemente do Devanagari acima da base), R4 abaixo da base (U+09C1-U+09C4, U+09E2-U+09E3), R5 pós-base (U+09BE, U+09C0, U+09D7). Não há matras acima da base no bloco principal do Bengali.
  • Decomposição de matra: `U+09CB` Oo e `U+09CC` AU se expandem para seus componentes visuais durante a reordenação (U+09C7 + U+09BE / U+09C7 + U+09D7), para que o pipeline GSUB os veja nas posições canônicas de prefixo e sufixo.
  • O dispatcher `ApplyIndicReorder` roteia transparentemente os pontos de código Bengali para a entrada Bengali; os utilitários `BuildUnicode*FieldContent` com `sfIndicShaping` definido agora cobrem Bengali, juntamente com Devanagari, sem alterações na integração.
  • Testes: 18 novos casos de teste DUnitX que abrangem os conjuntos de caracteres Bengali R1/R2/R4/R5, decomposição, preservação de conjunções, passagem de scripts mistos, idempotência e equivalência do despachante. No total, 69 de 69 testes foram aprovados no Win32 + Win64.
  • De acordo com a seção 12.2 da especificação Unicode 16.0 (Bengali) e a especificação de formatação Bengali do OpenType.

2026-05-23 Version 2.119.70

  • Atualização completa do mecanismo de formação de caracteres Devanagari (roteiro do motor GSUB, Fase 8f.1): `ApplyDevanagariReorder` agora aplica a regra completa de reordenação de 5 etapas (R1 Repha + R2 pré-base + R3 acima da base + R4 abaixo da base + R5 pós-base), em vez do subconjunto R1 + R2-only da versão v2.119.55. A ordem dos clusters de saída é por sílaba: `[pré-matras] + [base + halant + nukta + bindu/visarga/ modificador] + [matras superiores] + [matras inferiores] + [pós-matras] + [Repha]`.
  • Preservação de ligaduras: grupos de consoantes-halantes-consoantes permanecem agrupados no bloco base; a reordenação afeta apenas as vogais e o Repha. Processamento em uma única passagem e idempotente.
  • Alterações de comportamento em relação à versão v2.119.69: para sílabas que contêm matras superiores/inferiores/ pós-base (ou agrupamentos de múltiplas matras), o fluxo de bytes do PDF agora reflete o layout de reordenação canônica. A renderização visual após o GSUB/GPOS permanece inalterada. As entradas que contêm apenas o R1 Repha ou o I-matra de base prévia R2 (o subconjunto da versão v2.119.55) produzem uma saída idêntica em termos de bytes.
  • Testes: 8 novos casos de teste DUnitX que abrangem R3, R4 e R5 individualmente, a ordem de múltiplas marcas diacríticas, a preservação de conjunções sob marcas diacríticas, a combinação de Repha com acentos acima e abaixo, e a idempotência de múltiplas marcas diacríticas. No total, 51 de 51 testes foram aprovados no Win32 e Win64.
  • De acordo com a seção 12.1 do Unicode 16.0 (Devanagari) e a especificação de formação Devanagari do OpenType.

2026-05-23 Version 2.119.69

  • Infraestrutura de modelagem de escrita Indic (roteiro da fase 8f.0 do motor GSUB): refatoramos a pré-passagem de reordenação Devanagari v2.119.55 / v2.119.67 em um framework de despacho independente de script. Novos tipos `TIndicScriptInfo` / `TIndicCategoryFunc` / `TIndicFindSyllableFunc` / `TIndicReorderFunc` e um novo registro `IndicScripts` permitem que futuras escritas Indic sejam integradas por meio de ponteiros de função.
  • Um novo método público, `ApplyIndicReorder(Wide)`, direciona cada ponto de código de `Wide` para o script registrado correspondente e aplica as funções de callback de sílaba e reordenação desse script. O conteúdo não relacionado a scripts Indic é transmitido byte a byte.
  • As três funções auxiliares `BuildUnicode*FieldContent` agora invocam `ApplyIndicReorder` (em vez do wrapper específico para Devanagari) quando `sfIndicShaping` está em `FShapingFeatures`. A fase 8f.0 inclui apenas o suporte para Devanagari; as fases subsequentes, de 8f.2 a 8f.10, adicionam Bengali, Gujarati, Tamil, Telugu, Kannada, Malayalam, Sinhala, Khmer e Myanmar, sem alterar este ponto de integração.
  • A função `ApplyDevanagariReorder` existente foi mantida como um wrapper específico para Devanagari, para garantir a compatibilidade com versões anteriores da v2.119.55. A saída não foi alterada em relação à v2.119.67.
  • De acordo com a seção 12 da Unicode 16.0 (scripts sul-asiáticos) e a seção 9.10 da ISO 32000-1.

2026-05-22 Version 2.119.68

  • Fase 8c.6 — Emissão de GID no lado do produtor via mapeamento de codepontos sintéticos da Área de Uso Privado: dois novos métodos públicos em THotPDF permitem que os chamadores emitam GIDs substitutos que não possuem um codeponto Unicode natural, alocando codepontos sintéticos PUA (U+E000-U+F8FF) sob demanda. AssignSyntheticCodepointForGID (GID; out SyntheticCP): Boolean aloca o próximo slot PUA disponível, espelha a atribuição em FUnicodeCpToGid + FAcroFormUnicodeAdvances + uma nova tabela de pesquisa FUnicodeSyntheticCpForGID por GID, para que o pipeline de codificação hexadecimal existente do produtor emita o codeponto sintético como um token de 4 dígitos hexadecimais que o leitor do consumidor resolve através de /CIDToGIDMap para o glifo substituto. GetSyntheticCodepointForGID (GID): Word consulta atribuições existentes (retorna 0 quando nenhum codeponto sintético foi atribuído). Ambos os métodos são idempotentes — chamadas repetidas com o mesmo GID retornam o mesmo codeponto sintético.
  • Desbloqueia a emissão no lado do produtor para substituições GSUB específicas da fonte que não possuem codepontos de Forma de Apresentação Unicode: formas de cluster Devanagari (as saídas 'akhn' / 'rphf' / 'pres' / 'blws' / 'psts' / 'haln' normalmente ficam em GIDs internas da fonte), alternativas estilísticas ('salt' / 'ss01-20' sem codepontos), ligaduras discricionárias ('dlig' / 'hlig' - glifos específicos da fonte) e substituições de sequência de variação ideográfica CJK. Combinado com as APIs do motor GSUB v2.119.43-50 e o módulo de subsetagem MarkUnicodeGlyphUsed v2.119.50, os chamadores agora podem construir pipelines de formatação completos no lado do produtor que emitem GIDs de substituição arbitrárias através do pipeline hexadecimal baseado em codeponto existente.
  • O tempo de vida do estado: os mapeamentos sintéticos persistem até que RegisterUnicodeTTF seja chamado novamente ou BeginDoc seja executado (ambos redefinem todo o estado específico da fonte, incluindo a tabela sintética). O intervalo PUA U+E000-U+F8FF fornece 6400 slots, o que é suficiente para o conjunto de substituições GSUB de qualquer fonte prática. O mapeamento inverso CMap ToUnicode é responsabilidade do chamador — os codepoints PUA sintéticos não têm codepoints de origem para mapeamento inverso; os chamadores preocupados com a extração de texto devem envolver a emissão de texto em conteúdo marcado PDF com a propriedade /ActualText, especificando os codepoints de origem originais. PDFs cujos chamadores não invocam AssignSyntheticCodepointForGID produzem resultados idênticos aos da versão v2.119.67 (os novos métodos são auxiliares de consulta sem estado / alocação explícita; não há efeitos colaterais automáticos). Este commit completa a matriz de funcionalidades da Fase 8 do motor GSUB.

2026-05-22 Version 2.119.67

  • O pré-processamento automático de reordenação Devanagari (roteiro do motor GSUB, Fase 8e): os três utilitários BuildUnicode*FieldContent agora invocam automaticamente o método ApplyDevanagariReorder v2.119.55 quando sfIndicShaping está incluído em FShapingFeatures. O pré-processamento percorre a entrada da esquerda para a direita, aplicando as duas reordenações específicas do Devanagari (relocação de Repha para o Ra-Halant inicial da sílaba e movimentação do I-matra U+093F para o início do seu cluster de sílaba) para que o fluxo de codepontos emitido corresponda à ordem de leitura visual. O motor GSUB do leitor consumidor então aplica a cadeia de formação Indic ('nukt' / 'akhn' / 'rphf' / 'rkrf' / 'pref' / 'half' / 'vatu' / 'cjct' / 'pres' / 'blws' / 'abvs' / 'psts' / 'haln') contra os codepontos reordenados para produzir os glifos finais do cluster.
  • A fase 8e oferece apenas a reordenação no lado do produtor. A aplicação de cadeias GSUB no lado do produtor (onde o produtor define a formação de clusters no momento da geração do PDF, em vez de depender do leitor) foi adiada para a fase 8c.6, porque a maioria das substituições GSUB em Devanagari usa GIDs específicas da fonte, sem um codeponto de Forma de Apresentação Unicode. Ao contrário do árabe/latim, onde os blocos Forms-A/Forms-B fornecem substituições acessíveis por codeponto, o Devanagari não possui uma gama equivalente de Forma de Apresentação no Unicode. O mapeamento de codepontos sintéticos PUA na fase 8c.6 permitirá a emissão de GSUB no lado do produtor para Devanagari e outros scripts Indic/Sudeste Asiático, onde os GIDs de substituição são específicos da fonte.
  • Conteúdo que não é Devanagari passa pelo método ApplyDevanagariReorder, mantendo a identidade de bytes (o método apenas percorre sílabas Devanagari; outras faixas de codepontos são emitidas sem alterações). PDFs cujos chamadores deixam sfIndicShaping desativado (o padrão) geram uma saída idêntica à versão v2.119.66. Combinado com a camada de funcionalidade v2.119.55 (GetDevanagariCategory + ApplyDevanagariReorder como métodos públicos), este commit completa a integração de reordenação Devanagari no lado do produtor: os chamadores que habilitam sfIndicShaping não precisam mais pré-ordenar os dados anteriormente ou chamar ApplyDevanagariReorder manualmente antes de BuildUnicode*FieldContent — o HotPDF faz isso automaticamente.

2026-05-22 Version 2.119.66

  • GSUB 'rclt' (Alternativas Contextuais Obrigatórias): integração automática com o novo método THotPDF.ApplyArabicGSUBContextualRefinement (Wide), que funciona de forma semelhante ao v2.119.63 ApplyArabicGSUBRefinement, mas aplica substituições contextuais (GSUB Tipo 5 / 6) através da API v2.119.47 ApplyContextualSubst, em vez de substituições de ligaduras (Tipo 4). 'rclt' codifica substituições obrigatórias dependentes do contexto – normalmente usadas por fontes árabes para variantes posicionais adicionais além do mapeamento Forms-B do analisador estático v2.85.0, e por fontes do Sudeste Asiático / Índicas para formas reorganizadas no nível do cluster que dependem do contexto vizinho.
  • Tratamento de saída de comprimento variável: ao contrário de `ApplyLigatureSubstitution` (N GIDs de entrada -> 1 GID substituto), `ApplyContextualSubst` pode produzir M GIDs substitutos a partir de N GIDs de entrada. Quando uma regra contextual é acionada, TODOS os GIDs substitutos devem ser acessíveis através de pontos de código de Formato de Apresentação Unicode, por meio de um cmap inverso (FB00-FDFF + FE70-FEFF, aproximadamente 770 pontos de código analisados), para que a substituição seja confirmada; se qualquer substituto não tiver um mapeamento inverso, a janela de entrada é transmitida sem alterações (uma emissão parcial corromperia a sequência). A faixa do cmap inverso foi expandida para cobrir os Formatos de Apresentação Latino/Armênio/Hebraico (FB00-FB4F) e todos os intervalos árabes, para que os substitutos 'rclt' de qualquer script possam ser emitidos.
  • Novo membro do enum THPDFShapingFeature, sfContextualAlternates (adicionado no final para compatibilidade com versões anteriores — as chamadas existentes que usam FShapingFeatures permanecem inalteradas e compilam sem problemas). Integrado nos três auxiliares BuildUnicode*FieldContent, controlados por sfContextualAlternates em FShapingFeatures (opcional, padrão desativado). Independente de FAutoShapeArabic — 'rclt' pode ser aplicado a scripts não-árabes (Latim / Hebraico / Indic). Os GIDs substituídos são processados por MarkUnicodeGlyphUsed para o criador de subconjuntos v2.84.0. Implementação defensiva que não faz nada se a fonte não tiver regras 'rclt' ou se os GIDs substituídos não tiverem codepoints de Presentation Form. PDFs gerados com sfContextualAlternates desativado produzem resultados idênticos aos da versão v2.119.65.

2026-05-22 Version 2.119.65

  • As ligaduras padrão do alfabeto latino (roteiro da fase 8b do motor GSUB) agora são implementadas com o novo método THotPDF.ApplyLatinLigatureRefinement (Wide), que é semelhante ao v2.119.63 ApplyArabicGSUBRefinement, mas direcionado às formas de apresentação alfabéticas latina/armênia/hebraica em U+FB00-U+FB4F. O método percorre a string de entrada, cria um array GID paralelo usando FUnicodeCpToGid e consulta o recurso 'liga' (ligaduras padrão) do GSUB da fonte através da API v2.119.43-50 ApplyLigatureSubstitution em cada posição. Se uma substituição de ligadura for aplicada E o GID substituto for acessível através de um ponto de código da forma de apresentação alfabética Unicode, a janela de ponto de código de origem é substituída pelo ponto de código do substituto. Isso está integrado aos três auxiliares BuildUnicode*FieldContent (de linha única, multilinha e AcroForm /AP de aparência combinada) e é controlado por sfStandardLigatures em FShapingFeatures (opcional, e estável em bytes quando não definido).
  • Passo opcional secundário para 'clig' (Ligaduras Contextuais): quando `sfContextualLigatures` também está incluído em `FShapingFeatures`, o método percorre novamente o resultado pós-'liga' aplicando 'clig' para identificar ligaduras contextuais específicas da fonte, além do conjunto padrão de fi / fl / ffi / ffl. Cada GID de substituição gerado é passado por `MarkUnicodeGlyphUsed` para o módulo de subsetagem TTF da versão v2.84.0. A cmap reversa é uma varredura linear de aproximadamente 80 pontos de código (FB00-FB4F); as substituições são esparsas e o custo é insignificante.
  • 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 pública para consulta de avanço de ponto de código (roteiro do motor GSUB, Fase 8c.5): o novo método THotPDF.GetCodepointAdvance (CP: Cardinal) expõe o cache /W da versão v2.76.0, permitindo que os chamadores que criam cálculos personalizados de quebra de palavras fora da função BuildUnicodeMultilineFieldContent consultem o avanço em unidades de medida real para qualquer ponto de código, derivado da tabela hmtx da fonte por meio do cmap armazenado em cache. Após a cadeia estática de pós-processamento de ligaduras v2.119.32 / v2.119.58 / v2.119.60 / v2.119.62 e o refinamento GSUB no nível GID v2.119.63, que emitem pontos de código de ligaduras (LAM-ALEF FEF5-FEFC, YEH-HAMZA FBEA-FBFB, Allah FDF2, Bismillah FDFD e formas de apresentação substituídas por GSUB em FB50-FDFF / FE70-FEFF), o método retorna o avanço hmtx real do glifo da ligadura — geralmente mais estreito do que a soma dos avanços dos pontos de código de origem — para que os orçamentos de quebra de linha dos chamadores se alinhem com a renderização no lado do consumidor.
  • Refinamento da heurística para o preenchimento de conteúdo de campos Unicode multilinha: o caminho de fallback da versão 2.65 (usado quando o cache /W não está disponível, por exemplo, no caminho RegisterUnicodeFontDict em vez de RegisterUnicodeTTF) anteriormente tratava todos os pontos de código >= U+2E80 como "largos" (1,0 em). As formas de apresentação árabe (FB50-FBFF Forms-A letters, FC00-FDFF Forms-A ligatures + Quranic FDF0-FDFD, FE70-FEFF Forms-B basic shapes + LAM-ALEF) são, na verdade, "estreitas" (aproximadamente 0,55 em em média na maioria das fontes árabes), e não "largas". A versão 2.119.64 direciona esses três intervalos de formas de apresentação árabe para o caminho "estreito" (0,5 em) no fallback heurístico, corrigindo um caso especial em que as ligaduras árabes emitidas pelas etapas posteriores v2.119.32 / v2.119.58 / v2.119.60 / v2.119.62 / v2.119.63 teriam avanços incorretos de 1,0 em, caso o cache não estivesse preenchido.
  • Retorna 0 para o caminho padrão quando não há informações disponíveis (nenhuma fonte registrada, cache ainda não preenchido, codeponto acima do BMP, codeponto não possui glifo no cmap da fonte). É uma função pura, sem efeitos colaterais, e é seguro chamá-la de qualquer contexto após o sucesso de RegisterUnicodeTTF. PDFs cuja fonte carregada possui o cache "/W" preenchido e que não utilizam o novo método de consulta geram resultados idênticos em bytes à saída da versão v2.119.63. A fase 8c.5 finaliza o roteiro do motor GSUB §8c, implementando um pipeline de formação automática de caracteres árabes no lado do produtor, no nível de capacidade. As fases 8c.1 a 8c.5, em conjunto, fornecem pós-processamentos de tabelas estáticas (4 famílias de ligaduras) + mapeamento inverso ToUnicode + refinamento GSUB no nível GID + consulta de avanço pública, tudo trabalhando em conjunto para tornar a renderização de ligaduras árabes no lado do produtor precisa em termos de bytes, em comparação com a exibição no lado do consumidor.

2026-05-22 Version 2.119.63

  • Refinamento no nível de GID para a função 'rlig' do GSUB (fase 8c.2 do roteiro do motor GSUB): o novo método THotPDF.ApplyArabicGSUBRefinement (Wide) percorre a string de entrada da esquerda para a direita, construindo um array GID paralelo usando o cmap armazenado em cache (FUnicodeCpToGid), e em cada posição com GID diferente de zero, consulta a função 'rlig' (ligaduras obrigatórias) do GSUB da fonte através da API ApplyLigatureSubstitution v2.119.43-50. Se uma substituição de ligadura for aplicada E o GID do substituinte for acessível através de um codeponto de forma de apresentação árabe Unicode (varredura inversa do cmap através de U+FB50-U+FDFF + U+FE70-U+FEFF, aproximadamente 690 codepontos), a janela de codepontos da fonte original é substituída pelo codeponto do substituinte. Os glifos substitutos também são passados pelo MarkUnicodeGlyphUsed para o módulo de subsetor TTF v2.84.0.
  • Integrado nos três utilitários BuildUnicode*FieldContent imediatamente após a cadeia estática de pós-processamento de codepontos (LAM-ALEF / YEH-HAMZA / Allah / Bismillah) nas versões v2.85.0 / v2.119.32 / v2.119.58 / v2.119.60 / v2.119.62. Complementa a tabela estática, capturando regras específicas da fonte 'rlig' que as quatro famílias codificadas não incluem — exemplos típicos incluem variantes contextuais em fontes persas / urdu / sindhi / curdas (Vazirmatn, Markazi Text, Lateef, Scheherazade, Amiri) que mapeiam para Formas de Apresentação Unicode além do conjunto LAM-ALEF / YEH-HAMZA / Allah / Bismillah. É executado apenas quando FAutoShapeArabic é verdadeiro E sfArabicGSUB NÃO está em FShapingFeatures (o bloqueio mútuo preserva o caminho "controlado pelo chamador" da versão v2.119.59) E a fonte carregada possui uma tabela GSUB.
  • Escopo: apenas as substituições cujos GIDs são acessíveis através de um ponto de código de formulário de apresentação via cmap são emitidas. Substituições GSUB específicas da fonte que caem em IDs de glifos arbitrários (sem mapeamento inverso de ponto de código) não podem ser emitidas por este caminho — elas precisam de uma emissão completa no nível do GID na pipeline do produtor reservada para a Fase 8c.5+. O mapeamento inverso do cmap é uma varredura linear de aproximadamente 690 pontos de código por tentativa de substituição; as substituições são raras na prática, portanto, o custo é insignificante. PDFs cujo fonte carregado não possui conteúdo GSUB 'rlig' ou cujas substituições não possuem pontos de código de formulário de apresentação emitem bytes idênticos à saída v2.119.62 (neste caso, o método é uma operação defensiva sem efeito). Com esta alteração, a pipeline automática de formação de caracteres árabes do lado do produtor do motor GSUB ganha a capacidade de dobrar ligaduras com conhecimento da fonte, além da cadeia estática e codificada.

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.
  • A tabela CMap ToUnicode foi expandida com uma 28ª entrada de bfchar, que mapeia U+FDFD de volta à sequência de origem de 22 pontos de código (BEH + SEEN + MEEM + SPACE + ALEF + LAM + LAM + HEH + SPACE + ALEF + LAM + REH + HAH + MEEM + NOON + SPACE + ALEF + LAM + REH + HAH + YEH + MEEM). A extração de texto no lado do consumidor (copiar/colar/acessibilidade) agora restaura a frase original de 22 pontos de código em vez do único glifo de ligadura, completando o comportamento de ida e volta para as quatro famílias de ligaduras de tabela estática (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.
  • Cobertura: 8 entradas LAM-ALEF U+FEF5-U+FEFC (ligadura obrigatória v2.119.32, 4 variantes de ALEF × 2 formas) → pares de origem LAM + ALEF / ALEF MADDA / ALEF HAMZA ACIMA / ALEF HAMZA ABAIXO; 18 entradas da família YEH-HAMZA U+FBEA-U+FBFB (v2.119.58, inclui as formas iniciais FBF8 e FBFB que o processo automático posterior não produz, mas que os chamadores podem usar diretamente) → pares de origem YEH-HAMZA + ALEF / AE / WAW / U / OE / YU / E / ALEF MAKSURA; 1 entrada de Allah U+FDF2 (v2.119.60) → sequência de origem de quatro pontos de código ALEF + LAM + LAM + HEH. Com esta atualização, a cópia / colagem / acessibilidade em ciclo fechado está completa para as três famílias de ligaduras de tabela estática.
  • Estável para conteúdos não árabes: o bloco bfchar adiciona aproximadamente 700 bytes de texto PostScript não compactado ao fluxo CMap, o que o FlateDecode normalmente reduz para aproximadamente 150-200 bytes. PDFs sem conteúdo árabe ainda emitem o mesmo layout do fluxo /ToUnicode — a extensão é aditiva dentro do mesmo objeto de fluxo FlateDecode indireto. Leitores de consumo (Adobe Reader, Foxit, PDF.js, Apple Preview, etc.) respeitam a precedência de bfchar em relação a bfrange e aplicam o mapeamento inverso corretamente. O bloco de 27 entradas está codificado no texto do CMap (não é necessário nenhum ajuste personalizado por PDF); uma futura fase 8c.4 adicionará entradas bfchar adicionais para a ligadura 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

  • O novo framework de ativação opcional para o pipeline de formatação no lado do produtor (roadmap do motor GSUB, Fase 8a): a nova enumeração THPDFShapingFeature, juntamente com o tipo de conjunto THPDFShapingFeatures, modela as flags de recursos planejadas para as fases 8a a 8e, para a integração de formatação de texto no lado do produtor. Os cinco membros da enumeração são sfArabicGSUB (implementado nesta versão), sfStandardLigatures (Fase 8b, futuro), sfContextualLigatures (Fase 8b, futuro), sfStylisticAlternates (Fase 8d, futuro) e sfIndicShaping (Fase 8e, futuro). O THotPDF ganha uma propriedade ShapingFeatures do tipo THPDFShapingFeatures, com valor padrão [], (todas as funcionalidades desativadas); as chamadas na versão v2.119.32-58 produzem uma saída idêntica, desde que a propriedade permaneça com seu valor padrão.
  • sfArabicGSUB atua como um bloqueio contra o módulo de formatação árabe de tabela estática v2.85.0. Quando sfArabicGSUB é incluído em ShapingFeatures, os três utilitários BuildUnicode*FieldContent (construtores de fluxo de aparência AcroForm de linha única, multilinha e combinada) ignoram completamente o _ApplyArabicShaping — nenhuma reescrita de ponto de código de quatro posições v2.85.0, nenhuma pós-passagem LAM-ALEF v2.119.32, nenhuma pós-passagem YEH-HAMZA + vogal v2.119.58. O chamador é responsável por controlar a seleção de formatação árabe através das APIs do motor GSUB v2.119.43-50 (SetGSUBScript ('arab') + GetSingleSubstituteGlyph contra as tags de recursos 'init' / 'medi' / 'fina' / 'isol' + MarkUnicodeGlyphUsed para o redutor v2.84.0). Combinado com sfArabicGSUB, os chamadores que usam fontes árabes como Noto Sans Arabic / Amiri / Scheherazade / Markazi Text ou fontes semelhantes agora podem controlar a formatação GSUB árabe completa no lado da fonte no momento da criação, em vez de depender da alternativa de tabela estática.
  • 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 + ligadura de letra com vogal: o módulo de formatação árabe da versão v2.85.0 agora combina as 8 combinações de ligaduras codificadas no bloco Arabic Presentation Forms-A, de U+FBEA a U+FBFB, em um único ponto de codificação após a etapa de análise de 4 posições e a etapa posterior do LAM-ALEF v2.119.32. O mesmo modelo e integração de formatação são usados que no LAM-ALEF (substituição estática obrigatória, 2 formas de saída por ligadura). As combinações cobertas são: YEH-HAMZA + ALEF -> FBEA/FBEB (árabe padrão / persa / urdu), YEH-HAMZA + AE U+06D5 -> FBEC/FBED (caxemiro / uigur), YEH-HAMZA + WAW -> FBEE/FBEF (árabe padrão), YEH-HAMZA + U U+06C7 -> FBF0/FBF1 (uigur / cazaque / quirguiz), YEH-HAMZA + OE U+06C6 -> FBF2/FBF3 (o mesmo), YEH-HAMZA + YU U+06C8 -> FBF4/FBF5 (o mesmo), YEH-HAMZA + E U+06D0 -> FBF6/FBF7 (o mesmo), YEH-HAMZA + ALEF MAKSURA -> FBF9/FBFA (árabe padrão).
  • YEH-HAMZA é correspondido em sua forma original U+0626 ou em qualquer uma de suas formas estilizadas v2.85.0 (FE89 isolada, FE8A final, FE8B inicial, FE8C medial); a vogal seguinte é correspondida em sua forma original ou em qualquer uma de suas variantes estilizadas Forms-A (FBD7-FBD8 para U, FBD9-FBDA para OE, FBDB-FBDC para YU, FBE4-FBE7 para E) ou variantes estilizadas Forms-B v2.85.0 (FE8D-FE8E para ALEF, FEED-FEEE para WAW, FEEF-FEF0 para ALEF MAKSURA). A seleção da forma final (base + 1) segue a regra LAM-ALEF: quando o YEH-HAMZA é estilizado para a forma final FE8A ou a forma medial FE8C (ou seja, é precedido por uma letra de ligação dupla), a ligadura é emitida em sua forma final; caso contrário, a forma isolada é usada.
  • Limites de escopo: apenas as formas isoladas e finais (saída de 2 formas) são geradas por esta etapa posterior. As formas iniciais definidas pela Unicode, FBF8 (YEH-HAMZA + E) e FBFB (UIGHUR YEH-HAMZA + ALEF MAKSURA), não são produzidas — os chamadores que precisam dessas variantes de três formas devem acionar as pesquisas GSUB de contexto encadeado 'rlig' / 'clig' por meio de ApplyContextualSubst. Outras regiões de ligaduras árabes (Allah U+FDFA / FDFB, ligaduras decorativas em FC00-FDC7) requerem o acionamento GSUB 'rlig' / 'dlig' e permanecem fora do escopo do formador de tabela estática. Os PDFs que não contêm YEH-HAMZA seguidos por uma das oito vogais suportadas geram bytes idênticos à v2.119.57; a nova etapa posterior é executada apenas para as sequências específicas de 2 pontos de código.

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 das letras recém-classificadas possuem entradas estáticas de Presentation Forms-A em U+FB52-U+FBFC e agora são mapeadas diretamente pelo processador de tabela estática, sem a necessidade de um processador GSUB da fonte: 15 letras de conexão D de 4 formas (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, que é a letra 'h' padrão do Urdu, E U+06D0 → FBE4-FBE7 para árabe cazaque/quirguiz), e 11 letras de conexão R de 2 formas (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, que é a letra yeh no final da palavra em Urdu, YEH BARREE COM HAMZA ACIMA U+06D3 → FBB0-FBB1).
  • As letras HEH DOACHASHMEE e YEH BARREE merecem destaque especial porque seus slots Forms-A (FBAA-FBAD e FBAE-FBAF) foram incorretamente atribuídos pela correção v2.119.52 aos caracteres U+06C2 HEH GOAL WITH HAMZA ABOVE e U+06C3 TEH MARBUTA GOAL. Com a versão v2.119.56, essas associações incorretas foram removidas e, com a versão v2.119.57, os slots foram vinculados às letras originais corretas, garantindo que o histórico esteja limpo e que a confusão seja resolvida permanentemente. As letras no intervalo U+0672-U+06D5 que não possuem entradas de Presentation Forms-A no Unicode 16 (cerca de 50 pontos de código adicionais, principalmente variantes de REH / DAL / SEEN / SAD / TAH / AIN / FEH / QAF / KAF sem formas pré-codificadas) ainda participam da análise de classe de junção para que os caracteres vizinhos sejam formatados corretamente; os próprios caracteres são processados como pontos de código brutos e dependem das tabelas de pesquisa GSUB da fonte, sob o mecanismo GSUB v2.119.43-50, para sua própria seleção de forma. Compilado em 78018 linhas; os arquivos PDF que não contêm esses novos pontos de código geram arquivos idênticos aos da versão v2.119.56.

2026-05-22 Version 2.119.56

  • Correção de um bug relacionado à formatação de texto em árabe: a versão v2.119.52 introduziu mapeamentos incorretos para as formas de apresentação do árabe A para dois caracteres da região Urdu/Sindhi. O caractere U+06C2 HEH GOAL WITH HAMZA ABOVE foi mapeado para FBAA-FBAD, que é na verdade a faixa de codepontos para U+06BE HEH DOACHASHMEE; os leitores renderizariam o glifo Urdu Goal-Heh-with-Hamza como o glifo Urdu Heh-Doachashmee padrão. O caractere U+06C3 TEH MARBUTA GOAL foi mapeado para FBAE-FBAF, que é na verdade a faixa de codepontos para U+06D2 YEH BARREE; os leitores renderizariam Teh-Marbuta-Goal como a palavra Urdu Yeh-Barree. De acordo com o Unicode 16.0, nem U+06C2 nem U+06C3 possuem entradas de formas de apresentação A pré-codificadas; ambos devem passar inalterados como codepontos brutos (os leitores exibem corretamente usando a tabela cmap da fonte e qualquer formatação orientada por GSUB).
  • Correção: as duas entradas incorretas na tabela de consulta _ArabicShape Presentation Forms-A do formador de texto árabe do lado do produtor, na versão v2.85.0, foram removidas; U+06C2 e U+06C3 agora seguem para o caminho de passagem e são emitidos sem alterações. As entradas de classe de junção da versão v2.119.52 (D para U+06C2, R para U+06C3) são mantidas para que as letras adjacentes ainda escolham as formas posicionais corretas quando esses caracteres aparecem em uma palavra. A correção afeta apenas PDFs que contêm U+06C2 ou U+06C3 com o AutoShapeArabic habilitado; os PDFs que não contêm esses dois pontos de código são idênticos em bytes à saída da versão v2.119.55. A versão complementar v2.119.57 expande a cobertura do Forms-A para incluir letras adicionais persas/urdu/sindi/cachemir/uigur/cazaque/quirguiz, incluindo os HEH DOACHASHMEE e YEH BARREE genuinamente codificados em Forms-A, que o erro da versão v2.119.52 estava confundindo.

2026-05-22 Version 2.119.55

  • Capacidade de formatação Indic para Devanagari: dois novos métodos públicos em THotPDF abrangem o paradigma de formatação Indic que não se encaixa no analisador de classes de junção de 4 posições usado para Árabe / Siríaco / Mongol (v2.85.0 + v2.119.32-54). GetDevanagariCategory (CP) retorna a categoria silábica Indic simplificada (0 = Outro, 1 = Consoante, 2 = Vogal independente, 3 = Matra, 4 = Virama, 5 = Nukta, 6 = Bindu, 7 = Visarga, 8 = Danda, 9 = Dígito, 10 = ZWJ, 11 = ZWNJ, 12 = Modificador) de acordo com o Unicode 16.0 §12.1 + IndicSyllabicCategory.txt; a tabela cobre todo o bloco Devanagari U+0900-U+097F, incluindo as extensões Marwari / Sindhi / Védicas em U+0978-U+097F.
  • ApplyDevanagariReorder (Wide) percorre a string de entrada da esquerda para a direita e aplica a etapa de reordenação Devanagari a cada sílaba Devanagari encontrada, retornando uma UnicodeString reordenada, pronta para ser usada com cmap e GSUB. O conteúdo não Devanagari (Latim, dígitos, pontuação, outros scripts) é transmitido byte a byte. Duas reordenações são implementadas (as duas que são predominantes na formatação Devanagari real): (1) Repha — quando uma sílaba começa com Ra (U+0930) + Halant (U+094D) + Consoante, o par (Ra, Halant) é movido para o FIM da sílaba, para que o recurso GSUB 'rphf' da fonte o substitua pelo glifo Repha, que visualmente se conecta acima e à direita da base da sílaba; (2) I-matra de base — U+093F é movido para o INÍCIO da sílaba (após a remoção de qualquer Repha), para que o processamento GSUB da esquerda para a direita o veja à frente do cluster de consoantes, correspondendo à sua ordem de renderização visual.
  • O pipeline do chamador aplica a reordenação Devanagari ao texto na ordem lógica -> Define o subscrito G ('deva') -> percorre os pontos de código reordenados, aplicando as características GSUB ('nukt' / 'akhn' / 'rphf' / 'rkrf' / 'half' / 'vatu' / 'cjct' / 'pres' / 'blws' / 'abvs' / 'psts' / 'haln') usando GetSingleSubstituteGlyph + ApplyLigatureSubstitution + ApplyContextualSubst -> emite os GIDs resultantes para o fluxo de texto do PDF, chamando MarkUnicodeGlyphUsed (GID) para cada emissão, para o subsetter v2.84.0. Com a Fase A (v2.119.52, Arabic Extended-A), a Fase B (v2.119.53, capacidade Syriac), a Fase C (v2.119.54, capacidade Mongol) e a Fase D (v2.119.55, capacidade Devanagari Indic) implementadas, a lacuna da matriz "formatação Mongol / Syriac / Devanagari" está totalmente preenchida. Fora do escopo: scripts Indic Devanagari (Bengali, Tamil, Telugu, Gujarati — cada um tem seus próprios dados de categoria e regras de reordenação), regras de reordenação além de Repha + I-matra de base e formatação Devanagari automática no lado do produtor dentro de TextOut / BuildUnicode*FieldContent (reservado para a Fase 8 do roadmap do motor GSUB).

2026-05-22 Version 2.119.54

  • Capacidade de formatação do mongol: dois novos métodos públicos em THotPDF expõem a classe de junção do mongol (U+1800-U+18AF) e a análise contextual de 4 posições, permitindo que os chamadores controlem a formatação do texto mongol no lado do processador. GetMongolianJoiningClass (CP) retorna a classe de junção do mongol (0 = U não junção, 2 = D junção dupla, 4 = T transparente / seletor de variação) para qualquer ponto de código; a tabela cobre o mongol básico, além das extensões de letras Todo, Sibe, Manchu e Ali Gali (U+1820-U+1878 + U+1887-U+18A8 + ALI GALI DAGALGA U+18A9 + MANCHU ALI GALI LHA U+18AA) e classifica NIRUGU (U+180A), os três Free Variation Selectors FVS1-FVS3 (U+180B-U+180D) e as marcas vocálicas Ali Gali BALUDA / THREE BALUDA (U+1885-U+1886) como transparentes. GetMongolianPosition (Wide, Index) percorre o texto circundante, ignorando as marcas transparentes, e retorna 0 = isolado, 1 = final, 2 = inicial ou 3 = medial para a letra no índice baseado em 0.
  • Assim como no Syriac (v2.119.53), o Mongol não possui Formas de Apresentação pré-codificadas no Unicode — cada fonte compatível com o Mongol (Mongolian Baiti, Noto Sans Mongolian, Noto Serif Mongolian, etc.) utiliza o posicionamento via tabelas de consulta GSUB do OpenType em seus recursos 'init', 'medi', 'fina' e 'isol', sob a tag de script 'mong'. Portanto, a v2.119.54 segue o mesmo modelo de funcionalidade da v2.119.53; os chamadores combinam a saída de posicionamento com as APIs do motor GSUB (SetGSUBScript ('mong'), GetSingleSubstituteGlyph para a tag de recurso de posicionamento apropriada, MarkUnicodeGlyphUsed para o subsetador v2.84.0) para produzir GIDs formatados que são enviados diretamente para o fluxo de texto do PDF.
  • O mongol é escrito verticalmente, de cima para baixo, em seu modo de escrita nativo; o processador opera na ordem lógica dos pontos de código (predecessor/sucessor no fluxo de pontos de código), independentemente da orientação visual. A renderização real de cima para baixo é tratada no momento da emissão do PDF por meio de /WMode 1 (escrita vertical) ou rotação da matriz da fonte, e não pelo formatador. A classificação de Free Variation Selectors como transparente significa que o processador resolve corretamente as formas posicionais, mesmo quando um FVS segue uma letra; a pesquisa GSUB da fonte sob os recursos 'fina' / 'medi' / 'init' / 'isol' seleciona automaticamente a variante condicionada pelo FVS quando um FVS ocorre na sequência de entrada. A formação de Devanagari (Indic) permanece reservada para versões futuras, porque requer uma etapa de reordenação Indic prévia, conforme UAX #38 (reordenação de virama / cluster de consoantes / base), o que não se encaixa no processador de 4 posições usado para árabe / siríaco / mongol. A formação automática de mongol dentro de TextOut / BuildUnicode*FieldContent permanece reservada para a Fase 8 do roteiro do motor GSUB.

2026-05-22 Version 2.119.53

  • Capacidade de formatação siríaca: dois novos métodos públicos em THotPDF expõem a pesquisa de classe de junção siríaca (U+0700-U+074F) e a análise contextual de 4 posições, permitindo que os chamadores controlem a formatação do texto siríaco no lado do gerador. GetSyriacJoiningClass (CP) retorna a classe de junção SyriacShaping.txt do Unicode 16.0 (0 = U não junção, 1 = R junção à direita, 2 = D junção dupla, 4 = T transparente / NSM) para qualquer ponto de código; a tabela cobre todas as 35 letras siríacas no bloco base, além das extensões persa e sogdiana (PERSIAN BHETH / GHAMAL / DHALATH em U+072D-U+072F, SOGDIAN ZHAIN / KHAPH / FE em U+074D-U+074F) e classifica o ALAPH SUPERIOR (U+0711) e os sinais de combinação siríacos (U+0730-U+074A) como transparentes. GetSyriacPosition (Wide, Index) percorre o texto circundante, ignorando os sinais transparentes, e retorna 0 = isolado, 1 = final, 2 = inicial ou 3 = medial para a letra no índice baseado em 0.
  • Ao contrário do árabe (que possui blocos de formas de apresentação pré-codificados B U+FE70-U+FEFF e blocos A U+FB50-U+FBFF que permitem que o HotPDF reescreva diretamente os pontos de código para variantes formatadas), o bloco siríaco NÃO possui formas de apresentação pré-codificadas no Unicode — cada fonte compatível com siríaco (Estrangelo Edessa, Serto Jerusalem, East Syriac Adiabene, Noto Sans Syriac, etc.) utiliza o posicionamento via pesquisas GSUB OpenType em seus recursos 'init' / 'medi' / 'fina' / 'isol'. Portanto, a versão v2.119.53 inclui apenas a camada de funcionalidade; o chamador combina a saída de posicionamento com as APIs do motor GSUB v2.119.43-50 (SetGSUBScript ('syrc'), GetSingleSubstituteGlyph para a tag de recurso de posicionamento apropriada, MarkUnicodeGlyphUsed para o subsetor v2.84.0) para produzir GIDs formatados que são emitidos diretamente no fluxo de texto do PDF.
  • O escopo da forma terminal de Alaph: O Unicode §9.3 documenta duas características terminais contextuais ('fin2' aplicada após DALATH / RISH, 'fin3' aplicada após FINAL LAMADH) que as fontes siríacas usam para trocar o glifo final de Alaph. A versão v2.119.53 classifica Alaph (U+0710) como um caractere básico que se junta à direita e retorna apenas 0 (isolado) ou 1 (final); os chamadores que precisam da diferenciação 'fin2' / 'fin3' devem acionar as pesquisas contextuais encadeadas da fonte por meio de ApplyContextualSubst com essas tags de recurso. A formação de mongol e Devanagari (Indic) permanecem reservadas para versões futuras: o mongol usa Free Variation Selectors e harmonia vocálica, o Devanagari requer uma etapa de reordenação Indic de acordo com UAX #38, nenhum dos dois se encaixa no algoritmo de 4 posições no estilo siríaco. A formação automática siríaca dentro de TextOut / BuildUnicode*FieldContent permanece reservada para a Fase 8 do roteiro do motor GSUB.

2026-05-22 Version 2.119.52

  • Extensão de modelagem para a família de fontes Árabes: o modelador estático Árabe, implementado no lado do produtor na versão v2.85.0, agora cobre os caracteres restantes do bloco Arabic Extended-A (ALEF WASLA U+0671, NOON GHUNNA U+06BA, variantes de HEH U+06C0-U+06C3), o bloco Arabic Supplement U+0750-U+077F (letras Árabes africanas usadas em Hausa, Wolofal e outras línguas africanas) e a nova região Arabic Extended-A U+08A0-U+08FF (Árabe do Corão + letras estendidas de Wolofal/Hausa + marcas de combinação do Corão). As classes de junção são obtidas do arquivo ArabicShaping.txt do Unicode 16.0 e aplicadas durante a análise posicional de quatro posições na versão v2.85.0, para que os caracteres vizinhos escolham a forma correta (init / medi / fina / isol), independentemente da variante Árabe em que se encontrem.
  • As letras que possuem formas de apresentação estáticas pré-codificadas no bloco Arabic Presentation Forms-A (U+FB50-U+FBFF) agora são mapeadas diretamente para essas formas, sem a necessidade de um processador OpenType GSUB: ALEF WASLA -> FB50/FB51 (junção à direita, duas formas), NOON GHUNNA -> FB9E/FB9F (junção dupla conforme Unicode, mas apenas duas formas pré-codificadas; init/medi degradam graciosamente para isol), HEH COM YEH ACIMA -> FBA4/FBA5 (junção à direita, duas formas), HEH GOAL -> FBA6/FBA7/FBA8/FBA9 (junção dupla, quatro formas completas), HEH GOAL COM HAMZA ACIMA -> FBAA/FBAB/FBAC/FBAD (junção dupla, quatro formas completas), TEH MARBUTA GOAL -> FBAE/FBAF (junção à direita, duas formas). Combinado com a pós-passagem obrigatória de ligadura LAM-ALEF da versão v2.119.32 e o subconjunto central de 9 letras para persa/urdu da versão v2.119.35, o processador estático agora cobre praticamente todo o texto moderno em árabe, persa, urdu, sindhi, pashto, curdo, uigur, árabe do Alcorão e árabe africano (hausa, wolofal, etc.), sem depender da tabela GSUB da fonte.
  • O suplemento árabe (U+0750-U+077F) e a região de letras árabes estendidas A (U+08A0-U+08C7) não possuem formas de apresentação estáticas pré-codificadas; suas entradas de classe de junção permitem que os caracteres vizinhos se formem corretamente, mas as próprias letras permanecem como pontos de código brutos e dependem de uma fonte compatível com GSUB (ou das APIs do motor GSUB v2.119.43-50, controladas pelo chamador) para sua própria formação posicional. A região de marcas combinatórias do árabe estendido A para textos corânicos (U+08CA-U+08E1, U+08E3-U+08FF) é classificada como transparente (junção T), portanto, a análise posicional dos caracteres vizinhos a ignora, correspondendo ao tratamento existente para harakat U+064B-U+065F. O texto que não inclui esses caracteres estendidos permanece idêntico em bytes à saída da versão v2.119.51. A formação do mongol, siríaco e devanágari (modelos de formação diferentes do árabe) permanecem reservados para revisões futuras.

2026-05-22 Version 2.119.51

  • Suporte a contêineres do lado do produtor para XFA (XML Forms Architecture): o PDF 1.7 §12.7.6 + §12.7.8 permite que um AcroForm carregue uma entrada /XFA junto com (ou em vez de) o array estático /Fields. O novo THotPDF.AddXFAPacket (PacketName, XMLBytes) registra um pacote XFA com um nome — nomes típicos são 'template' (layout do formulário + scripts), 'datasets' (vinculação de dados), 'config' (configuração do visualizador), 'connectionSet', 'localeSet', 'stylesheet', 'xfdf', 'xmpmeta', 'signature' e 'sourceSet'. Cada pacote registrado se torna um fluxo FlateDecode compactado indireto no final do documento, e o array /XFA alterna strings de nomes de pacotes com referências de fluxo na ordem de registro, para que o layout seja determinístico em termos de bytes. THotPDF.ClearXFAPackets e THotPDF.XFAPacketCount completam a superfície da API.
  • O suporte é apenas no nível do contêiner — o HotPDF não analisa o XML XFA, não implementa o mecanismo de layout dinâmico XFA, não executa FormCalc ou JavaScript dentro do modelo XFA e não valida a estrutura do modelo. O chamador cria o XML XFA (geralmente usando o Adobe LiveCycle Designer ou criando manualmente com base na especificação XFA 3.3) e o HotPDF emite os bytes exatamente como estão. Leitores que possuem um mecanismo XFA (versões mais antigas do Acrobat/Reader, FormsCentral, alguns produtos para quiosques) renderizam o formulário; leitores que não possuem um mecanismo XFA (Adobe Reader DC a partir de 2017, a maioria dos leitores de código aberto) exibem os campos AcroForm de fallback, se o documento for um fluxo de trabalho híbrido AcroForm + XFA.
  • Regras de conformidade PDF/A e PDF/X: As seções ISO 19005-1 §6.4.2 / ISO 19005-2 §6.4.2 / ISO 19005-3 §6.4.2 proíbem explicitamente o uso de formulários XFA (o mecanismo de layout dinâmico não pode ser arquivado de forma determinística). Os fluxos de trabalho de pré-impressão ISO 15930 rejeitam completamente os formulários interativos. A função AddXFAPacket gera um erro imediatamente se houver algum valor em PDFACompliance ou PDFXCompliance que não esteja em conformidade com a especificação relevante. Nomes de pacotes duplicados geram um erro. Um PacketName vazio ou XMLBytes vazios geram um erro. A função RequirePDFVersion (pdf15) aumenta automaticamente a versão do documento. O dicionário AcroForm é agora emitido quando /Fields contém pelo menos uma entrada OU pelo menos um pacote XFA foi registrado; as chamadas anteriores à versão v2.119.51 que não registram nenhum pacote mantêm a saída /AcroForm idêntica em bytes.

2026-05-22 Version 2.119.50

  • O módulo de subsetagem de TTF agora inclui um recurso para lidar com glifos substituídos pelo GSUB: a nova função THotPDF.MarkUnicodeGlyphUsed (GID: Word) adiciona um glifo ao conjunto de subsetagem da versão v2.84.0, independentemente de o cmap ter ou não um codeponto correspondente a esse glifo. A função de subsetagem da versão v2.84.0 deriva o conjunto de glifos usados de FUnicodeUsedCps através do cmap, portanto, todos os glifos substituídos introduzidos pelo GSUB – alternativas estilísticas, ligaduras, variantes contextuais e toda a saída das APIs de consulta de Fase 1 a 6 – estavam anteriormente invisíveis para o módulo de subsetagem, e o leitor renderizava .notdef em seu lugar. Agora, após emitir qualquer GID retornado por GetSingleSubstituteGlyph / GetMultipleSubstituteGlyphs / GetAlternateGlyph / ApplyLigatureSubstitution / ApplyContextualSubst / ApplyReverseChainedContextualSubst em um fluxo de texto PDF, o chamador agora chama MarkUnicodeGlyphUsed (GID) uma vez para cada GID emitido, para incluí-lo no conjunto de subsetagem incorporado.
  • O utilitário é idempotente (chamadas repetidas com o mesmo GID não têm efeito), robusto (GID >= FUnicodeNumGlyphs é descartado silenciosamente, chamadas feitas antes de qualquer RegisterUnicodeTTF são ignoradas) e se integra com a etapa de fechamento de glifos compostos v2.84.0 dentro de _BuildSubsetTTF: os chamadores precisam apenas marcar o GID do glifo substituto de nível superior — os componentes compostos são automaticamente carregados pela rotina _TTFWalkCompositeClosure existente. O conjunto é alocado de forma preguiçosa na primeira chamada e é redefinido como vazio a cada RegisterUnicodeTTF ('', nil), juntamente com o restante do estado do subconjunto. Com a implementação da Fase 9, cada consulta de API GSUB das Fases 1 a 7 pode ser usada com segurança em conjunto com a emissão de subconjuntos, sem que os glifos substitutos sejam removidos da fonte incorporada.

2026-05-22 Version 2.119.49

  • OpenType GSUB Script / LangSys selection API: cinco novos métodos públicos em THotPDF permitem que os chamadores associem as tabelas de substituição GSUB a um script e idioma específicos, em vez do mecanismo de fallback DFLT-script / default-LangSys histórico. SetGSUBScript ('latn' / 'arab' / 'cyrl' / 'hani' / 'kana' / 'deva' / 'beng' / 'taml' / etc.) seleciona uma tag de script OpenType; a string vazia padrão mantém o comportamento da versão v2.119.43-48 (é preferível 'DFLT', caso contrário, é usado o primeiro script). SetGSUBLanguage ('ENG ' / 'TUR ' / 'AZE ' / 'JAN ' / 'KOR ' / 'ARA ' / etc., preenchida com espaços para 4 bytes) seleciona uma tag de idioma OpenType; uma string vazia é o LangSys padrão do script. Ambas as configurações persistem durante as consultas GSUB e são redefinidas para vazio em RegisterUnicodeTTF ('', nil).
  • Três novos utilitários de enumeração expõem as informações que a fonte carregada anuncia: `GetGSUBScripts`: `TGSUBStringArray` retorna cada tag de script na ordem da lista de scripts; `GetGSUBLanguages (ScriptTag)` retorna cada tag de idioma sob o script fornecido (com um espaço reservado '' no índice 0 quando o script tem um `LangSys` padrão); `GetGSUBFeatures (ScriptTag, LangTag)` retorna cada tag de recurso (por exemplo, 'liga', 'salt', 'aalt', 'ss01' até 'ss20') anunciada pelo caminho (script, idioma) na ordem de `featureIndices` de `LangSys`. `ScriptTag` / `LangTag` vazios usam o mesmo mecanismo de fallback DFLT-first / `default-LangSys` que as APIs de substituição, permitindo que os chamadores chamem `GetGSUBFeatures ('', '')` para enumerar os recursos do caminho padrão sem primeiro inspecionar a lista de scripts.
  • Semântica de seleção estrita versus fallback: quando SetGSUBScript é definido para uma tag que a fonte carregada não anuncia, consultas subsequentes de GSUB retornam resultados vazios/sem efeito — o mecanismo NÃO faz fallback silenciosamente para DFLT, para que os chamadores possam saber claramente que o script escolhido está indisponível. Quando SetGSUBLanguage é definido para uma tag não reconhecida, ele faz fallback para o LangSys padrão do script, conforme a recomendação da especificação OpenType. Os sete métodos de substituição GSUB existentes (GetSingleSubstituteGlyph / GetMultipleSubstituteGlyphs / GetAlternateGlyphCount / GetAlternateGlyph / ApplyLigatureSubstitution / ApplyContextualSubst / ApplyReverseChainedContextualSubst) mantêm suas assinaturas públicas idênticas em bytes; apenas o helper interno _GSUBFindFeatureLookups ganha dois parâmetros adicionais que todos os sete pontos de chamada agora encaminham. Com a API Script / LangSys e a matriz LookupType 1-8 implementadas, o mecanismo GSUB está completo em termos de recursos para uso apenas em termos de capacidade; as fases restantes do roteiro (pipeline de modelagem automática + finalização do subsetor TTF) visam a integração no lado do produtor, em vez de novas superfícies de consulta.

2026-05-22 Version 2.119.48

  • OpenType GSUB Substituição Contextual Encadeada Inversa (LookupType 8): o novo THotPDF.ApplyReverseChainedContextualSubst (const InputGIDs; StartIndex; FeatureTag; out OutGID): Boolean é o último tipo de pesquisa GSUB a ser implementado. O tipo 8 realiza uma substituição única 1:1 que depende do contexto, onde o glifo de substituição é selecionado pelo índice de cobertura do glifo de entrada, e sua característica distintiva é que os chamadores devem aplicá-lo em ordem de varredura REVERSA sobre uma sequência de vários glifos (do final para o início), porque cada substituição pode depender do contexto de "olhar para o futuro" que ainda não foi substituído. Este utilitário é um aplicador de ponto único — o chamador controla o loop de varredura reversa. Os formatos de cobertura 1 + 2, a flag Lookup que respeita (entrada + retrocesso + olhada para o futuro, todos com consciência de "skip"), e o encapsulamento de extensão (LookupType 7) são todos suportados.
  • Caso de uso canônico: certas alternativas contextuais árabes / siríacas / N'Ko / indicas cuja forma final depende da forma específica do glifo seguinte. Algumas fontes também implementam isso para desambiguação de sequências latinas. Ao contrário de LookupType 5/6, o Type 8 não possui mecanismos de pesquisa aninhados, pois a substituição é intrinsecamente 1:1. Se não houver correspondência, retorna False. OutGID = InputGIDs[StartIndex] (correspondência de melhor esforço, seguindo o contrato do GetSingleSubstituteGlyph v2.119.43).
  • Corrige a matriz LookupType: com a versão v2.119.48, cada tipo de pesquisa GSUB do OpenType (de 1 a 8) possui uma capacidade pública dedicada no THotPDF. A seleção de script/sistema de idioma, a integração automática do pipeline de formação de caracteres e a extração automática de glifos substitutos do subsetor TTF permanecem reservados para as fases 7 a 9; os chamadores ainda são responsáveis por marcar os glifos substitutos escolhidos no subset de fontes incorporado e por controlar o loop de varredura reversa.

2026-05-22 Version 2.119.47

  • OpenType GSUB Substituição Contextual + Substituição Contextual Encadeada (LookupType 5 + 6): a nova função THotPDF.ApplyContextualSubst (const InputGIDs; StartIndex; FeatureTag; var OutGIDs; out ConsumedLen): Boolean é um ponto de entrada único que cobre tanto o LookupType 5 (contexto somente de entrada) quanto o LookupType 6 (contexto de retrocesso / entrada / antecipação) em todos os três formatos de subtabela — Formato 1 (sequências literais de ID de glifo), Formato 2 (sequências de classe ClassDef) e Formato 3 (sequências de tabela de cobertura, a forma canônica usada pela maioria das fontes modernas). Os usuários canônicos são 'rclt' (Alternativas Contextuais Obrigatórias — formas posicionais árabes init/medi/fina/isol quando a fonte as controla por meio do GSUB), 'clig' (Ligaduras Contextuais), 'calt' (Alternativas Contextuais) e os recursos de modelagem Indic 'pres' / 'blws' / 'psts' / 'half' / 'pstf' / 'cjct'.
  • O novo dispatcher de pesquisa aninhada SequenceLookupRecord: quando uma regra contextual é correspondida, cada entrada do SequenceLookupRecord dispara uma pesquisa aninhada em uma posição específica dentro da sub-sequência de entrada correspondente. O novo utilitário _GSUBApplyNestedLookup reentra na lista de pesquisa GSUB, resolve wrappers de extensão de forma transparente e direciona para os aplicadores Single (Tipo 1) / Multiple (Tipo 2) / Alternate (Tipo 3, primeira alternativa) / Ligature (Tipo 4). O dispatcher rastreia os índices de MatchPositions[] ativos para que as entradas subsequentes do SequenceLookupRecord continuem a endereçar as posições de trabalho corretas, mesmo quando uma substituição Multiple expande 1→N ou uma substituição Ligature colapsa N→1 glifos ao seu redor. A pesquisa aninhada do Tipo 5 / 6 / 8 (contextual recursivo) é intencionalmente adiada; a maioria das fontes reais usa pesquisas aninhadas para os Tipos 1 / 4.
  • Quando ocorre uma correspondência, o método retorna True juntamente com a sequência de glifos de saída que deve substituir InputGIDs[StartIndex..StartIndex+ConsumedLen-1]. O comprimento de OutGIDs pode ser diferente de ConsumedLen quando ocorrem pesquisas aninhadas de 1 para N ou de N para 1. ConsumedLen é sempre a extensão total da entrada que a regra contextual absorveu (incluindo as marcas ignoradas pela LookupFlag entre os glifos significativos); um chamador típico de um loop de varredura avança em ConsumedLen e emite OutGIDs. Quando não há correspondência, retorna False, OutGIDs vazio, ConsumedLen = 1 — o mesmo contrato seguro de operação nula das funções auxiliares v2.119.43-46. A flag LookupFlag (Fase 4) é aplicada durante toda a correspondência contextual: o retrocesso, a entrada e a análise antecipada ignoram todos os glifos marcados para ignorar. Script / LangSys permanecem fixos no padrão DFLT para esta fatia; a API de seleção está no escopo da Fase 7.

2026-05-22 Version 2.119.46

  • OpenType GSUB Extension Lookups (LookupType 7): o motor GSUB agora descompacta automaticamente as subtabelas de substituição de extensão — uma camada de indireção que a especificação OpenType define para fontes muito grandes, cujas tabelas de substituição reais estão além do alcance de 16 bits do Offset16 da LookupList. Cada API pública v2.119.43-45 (GetSingleSubstituteGlyph / GetMultipleSubstituteGlyphs / GetAlternateGlyphCount / GetAlternateGlyph / ApplyLigatureSubstitution) segue automaticamente a indireção de 32 bits para a tabela real do LookupType 1 / 2 / 3 / 4. Esta é a alteração no layout binário que permite o uso de fontes CJK / Indic OpenType grandes (Noto Sans CJK, Noto Sans Devanagari, etc.), cujas tabelas GSUB excedem 64 KB e que, anteriormente, tinham suas tabelas de pesquisa ocultas por wrappers do LookupType 7; anteriormente, essas fontes pareciam não ter recursos para o HotPDF.
  • Análise da tabela GDEF (Definição de Glifos) do OpenType: RegisterUnicodeTTF agora também armazena em cache a tabela GDEF da fonte, quando presente. Três sub-tabelas GDEF controlam a lógica de tratamento de LookupFlag: GlyphClassDef classifica cada GID como base (1) / ligadura (2) / marca (3) / componente (4); MarkAttachClassDef atribui a cada glifo de marca uma classe de anexação; MarkGlyphSetsDef (v1.2+) declara conjuntos nomeados de glifos de marca. Tanto o formato de ClassDef 1 (startGlyphID + classValueArray) quanto o formato 2 (classRangeRecords ordenados) são implementados; todos os cabeçalhos GDEF v1.0 / v1.1 / v1.2 são aceitos (o itemVariationStore v1.3 é ignorado). Fontes sem uma tabela GDEF retornam ao comportamento padrão v2.119.43-45 ("nenhum glifo é ignorado"), preservando a saída byte a byte para aplicativos que usam fontes que não possuem GDEF.
  • OpenType GSUB: agora, todas as cinco APIs públicas do GSUB leem o valor de LookupFlag de cada tabela de Lookup (e o uint16 opcional trailing markFilteringSet quando LookupFlag.useMarkFilteringSet estiver definido) e ignoram os glifos de entrada marcados para ignorar. Os bits de flag definidos na especificação são respeitados: 0x0002 ignoraBaseGlyphs (ignora a classe 1 de GDEF.GlyphClassDef), 0x0004 ignoraLigaduras (ignora a classe 2), 0x0008 ignoraMarks (ignora a classe 3), 0x0010 useMarkFilteringSet (apenas as marcas no MarkGlyphSet nomeado participam) e o byte alto markAttachmentType (apenas as marcas com a MarkAttachClassDef especificada participam). Para a substituição de ligaduras (LookupType 4), isso é o mais importante: as ligaduras 'rlig' árabes / 'akhn' indicas cujos componentes são separados por glifos de marca (por exemplo, LAM + Fatha + ALEF) agora correspondem corretamente quando LookupFlag.ignoreMarks está definido, e o ConsumedCount retornado inclui as marcas ignoradas, para que o loop de leitura do chamador avance por cada glifo de entrada absorvido. O bit 0x0001 (rightToLeft) é específico do GPOS e continua sendo ignorado para as pesquisas do GSUB.
  • As mesmas proteções continuam aplicáveis: fontes sem uma tabela GSUB, chamadas que passam uma tag que não tem 4 bytes, recursos que o script DFLT da fonte não anuncia, GIDs que nenhuma sub-tabela cobre, e agora, glifos de entrada ignorados pela LookupFlag, todos retornam o resultado seguro e inofensivo v2.119.43-45. As cinco assinaturas de API públicas são estáveis em relação ao tamanho dos bytes; apenas a busca interna agora inclui o despacho de extensões, o respeito pela LookupFlag e a classificação GDEF. A API de seleção de script/sistema de idioma, a integração automática do pipeline de formação e a extração automática de glifos substitutos pelo subsetor TTF permanecem reservados para revisões futuras.

2026-05-22 Version 2.119.45

  • Substituição de ligaduras GSUB do OpenType (LookupType 4): a nova função THotPDF.ApplyLigatureSubstitution (const InputGIDs: array of Word; StartIndex; FeatureTag; out OutGID; out ConsumedCount): Boolean combina uma sequência de vários glifos em um único glifo de ligadura. Os usuários canônicos são 'liga' (Ligaduras padrão — fi / fl / ffi / ffl), 'clig' (Ligaduras contextuais), 'dlig' (Ligaduras discricionárias), 'hlig' (Ligaduras históricas), 'rlig' (Ligaduras obrigatórias — LAM-ALEF árabe e similares quando a fonte controla a formação através do GSUB) e os recursos de ligaduras de scripts indicianos ('akhn', 'pres', 'blws', 'psts'). O chamador passa a sequência de ID de glifo pós-cmap e uma posição inicial baseada em 0; em uma correspondência completa, a função retorna True, OutGID = o glifo de substituição da ligadura e ConsumedCount = o número total de componentes de entrada consumidos (>= 2 na prática). Se não houver correspondência, retorna False, OutGID = 0, ConsumedCount = 1, para que o chamador possa avançar um passo e continuar a busca. A implementação segue a convenção do OpenType de que as entradas de LigatureSet são normalmente listadas da mais longa para a mais curta, permitindo que fontes com prefixos sobrepostos (por exemplo, uma ligadura 'ffi' de três componentes junto com uma ligadura 'ff' de dois componentes) tenham a correspondência mais longa. O mesmo contrato de segurança das funções v2.119.43/.44: tag vazia / não de 4 bytes, sem GSUB, recurso não anunciado, StartIndex fora do intervalo e nenhuma sub-tabela LookupType 4 correspondente na posição, todos retornam a operação segura (False / OutGID = 0 / ConsumedCount = 1). O descarte de marca LookupFlag, a integração GDEF GlyphClassDef, a aplicação automática durante a emissão de texto e a extração automática de glifos de ligadura pelo subsetor TTF permanecem reservados para revisões futuras.

2026-05-22 Version 2.119.44

  • OpenType GSUB Substituição Múltipla (LookupType 2): a nova função THotPDF.GetMultipleSubstituteGlyphs (InputGID, FeatureTag, var OutGIDs) retorna um glifo de entrada como uma sequência de glifos substitutos. O usuário principal é o recurso de Composição/Decomposição de Glifos 'ccmp', que divide letras latinas acentuadas pré-compostas em base + marcas combinatórias para posicionamento posterior das marcas. A função auxiliar percorre o mesmo caminho de script DFLT / LangSys padrão / FeatureList / LookupList que a função GetSingleSubstituteGlyph da versão v2.119.43 e aplica cada subtabela do tipo LookupType 2 conectada ao recurso solicitado em relação ao InputGID; a primeira correspondência é a vencedora. OutGIDs é redefinido na entrada para que os chamadores não precisem limpar previamente. Uma sequência vazia permitida pela especificação (glyphCount = 0, exclusão canônica de glifos Unicode) é relatada como Result = True com Length(OutGIDs) = 0 para que o chamador possa descartar o glifo de entrada da sequência.
  • OpenType GSUB Substituição Alternativa (LookupType 3): dois novos métodos expõem o ciclo completo de glifos alternativos para recursos estilísticos. THotPDF.GetAlternateGlyphCount (InputGID, FeatureTag) retorna o número de formas alternativas que uma fonte oferece para InputGID sob FeatureTag, e THotPDF.GetAlternateGlyph (InputGID, FeatureTag, AlternateIndex) retorna o glifo alternativo no índice solicitado, começando em 0. Os usuários canônicos são 'aalt' (Acessar Todas as Alternativas), 'salt' (Alternativas Estilísticas), 'titl' (Alternativas de Título) e 'ss01' a 'ss20' (Conjuntos Estilísticos 1-20) quando usados com LookupType 3 em vez de LookupType 1; na versão v2.119.43, GetSingleSubstituteGlyph ignorava silenciosamente essas subtabelas, então os chamadores de 'aalt' anteriormente viam apenas as substituições transitivas do LookupType 1. Essa combinação permite que os chamadores percorram ciclos de glifos decorativos (diferentes formas de 'a', 'g' e '7'), variantes de letras maiúsculas e alternativas de conjuntos estilísticos de forma explícita. Se AlternateIndex estiver fora do intervalo ou for negativo, ele retorna InputGID inalterado, permitindo que os chamadores investiguem com segurança.
  • Ambos os utilitários seguem o mesmo contrato de segurança da versão v2.119.43: fontes sem uma tabela GSUB, chamadores que passam uma tag que não tem 4 bytes, recursos que o script DFLT da fonte não anuncia, e GIDs que a subtabela LookupType 2/3 não cobre, retornam a operação segura sem efeito (False + OutGIDs vazios para Multiple; 0 / InputGID para Alternate). As subtabelas LookupType 1/4-8 encontradas na cadeia de pesquisa do recurso são ignoradas silenciosamente nesta versão. O filtragem de LookupFlag, a integração de GlyphClassDef (GDEF), a seleção de Script/LangSys, a integração automática do pipeline de formação e a extração automática de glifos substitutos pelo subsetor TTF permanecem reservados para futuras revisões; os chamadores ainda são responsáveis por marcar os glifos escolhidos no subconjunto da fonte incorporada.

2026-05-22 Version 2.119.43

  • OpenType GSUB: a nova função THotPDF.GetSingleSubstituteGlyph (InputGID, FeatureTag) percorre a cadeia GSUB ScriptList / FeatureList / LookupList da fonte, sob o LangSys padrão do script DFLT, e aplica cada subtabela do tipo LookupType 1 (substituição única) associada à característica solicitada, retornando o ID do glifo substituído. As características mais comuns para alternativas estilísticas são 'salt' (alternativas estilísticas), 'ss01' a 'ss20' (conjuntos estilísticos 1-20), 'aalt' (use todas as alternativas), 'titl' (alternativas para títulos), 'subs' / 'sups' (subscrito / sobrescrito), 'frac' (frações) e 'ordn' (ordinais); qualquer tag de característica OpenType de 4 bytes cuja cadeia de características contenha subtabelas do tipo LookupType 1 é suportada. Tanto o Formato de Cobertura 1 (array de glifos ordenado, pesquisado em binário) quanto o Formato 2 (registros de intervalo) são suportados. Tanto o Formato de Substituição Única 1 (delta) quanto o Formato 2 (array de substituição) são implementados. RegisterUnicodeTTF agora armazena em cache o deslocamento/tamanho da tabela GSUB junto com o cmap, para que as consultas GSUB evitem a reanálise do diretório da tabela. Fontes sem uma tabela GSUB, chamadores que passam uma tag de 4 bytes que o script DFLT da fonte não anuncia, e GIDs que não estão na cobertura da pesquisa, todos retornam InputGID inalterado, portanto, a API é segura para ser chamada como uma substituição ou passagem de dados. As subtabelas do tipo LookupType 2-8 encontradas na cadeia de pesquisa da característica são ignoradas silenciosamente nesta primeira etapa — as cadeias de substituição múltipla / substituição alternativa / substituição de ligaduras e a integração do pipeline de formação automática são reservadas para revisões futuras.

2026-05-22 Version 2.119.42

  • AcroForm /DR Resources agora aceita múltiplas fontes Unicode. Na versão v2.56.0, SetFormUnicodeFontDict rastreia apenas uma fonte fornecida pelo usuário, que se torna a fonte padrão do AcroForm /DA; formulários multilíngues que precisam de scripts diferentes por campo (árabe + CJK + latim em um único PDF) precisavam criar manualmente o dicionário /DR /Font. A nova função THotPDF.RegisterAcroFormFont (LogicalName, FontDict) registra uma fonte Unicode adicional com qualquer nome lógico, tornando-a disponível para strings /DA por campo (/ 12 Tf) e a emite no dicionário /DR /Font do AcroForm, juntamente com a fonte padrão da versão v2.56.0. A ordem de registro é preservada, para que o /DR emitido seja determinístico. Conflitos de nome com a fonte padrão do SetFormUnicodeFontDict ou uma fonte registrada anteriormente geram um erro com o nome ofensivo. Nomes lógicos vazios ou FontDict nulos também geram um erro. O caminho de reset do SetFormUnicodeFontDict ('', nil) também limpa o registro de fontes adicionais, para que um novo fluxo de trabalho Unicode comece a partir de um estado conhecido e limpo. Permitido em todos os níveis PDF/A / PDF/X — fontes Unicode compostas são metadados estruturais do formulário, e não scripts interativos.

2026-05-22 Version 2.119.41

  • Enumeração de estrutura padrão que cobre a Tabela 333 da seção §14.8.4 do PDF 1.7: a nova enumeração THPDFStandardStructureType lista os ~40 papéis de estrutura prescritos pela especificação, agrupados por seu "bucket" de função no PDF (Agrupamento: Documento / Parte / Artigo / Seção / Divisão / Citação / Legenda / Sumário / Índice / Não estruturado / Privado; Nível de bloco: H / H1-H6 / P / L / LI / Lbl / LBody / Tabela / TR / TH / TD / THead / TBody / TFoot; Nível de linha: Span / Citação / Nota / Referência / Entrada de bibliografia / Código / Link / Anotação; Ruby + Warichu: Ruby / RB / RT / RP / Warichu / WT / WP; Ilustração: Figura / Fórmula / Formulário). Duas funções auxiliares de nível de unidade convertem a enumeração em nomes de PDF exatamente como especificados — StandardStructureTypeToName (T) retorna o nome sensível a maiúsculas e minúsculas usado como a chave /S do elemento de estrutura, e IsStandardStructureType (Name) testa uma string Ansi arbitrária em relação ao conjunto padrão, para que os chamadores possam verificar antecipadamente nomes de função personalizados e encaminhá-los através de AddStructRoleMap quando necessário. Uma nova sobrecarga da enumeração AddStructureElement aceita diretamente THPDFStandardStructureType, eliminando o risco de erros de digitação/sensibilidade a maiúsculas e minúsculas ("Para" vs "P", "Lbody" vs "LBody") das sobrecargas de string aberta, ao mesmo tempo que encaminha para a mesma implementação base. As sobrecargas existentes baseadas em AnsiString permanecem idênticas em bytes para os chamadores que usam nomes personalizados ou roteados pelo RoleMap.

2026-05-22 Version 2.119.40

  • Definidores de atributos de elementos de estrutura: três novas funções auxiliam no preenchimento dos atributos de texto em PDF para cada elemento, que são usados em conjunto com as versões v2.88.0 /Alt + /ActualText e v2.95.0 /ID. THotPDF.SetStructureElementLanguage (Elem, BCP-47 Lang) escreve PDF 1.7 §14.9.2 /Lang, substituindo a linguagem padrão do documento para o conteúdo abaixo deste elemento até que outra substituição /Lang seja aplicada — o uso típico é para trechos citados em outro idioma ou seções de conteúdo misto. THotPDF.SetStructureElementExpansionText (Elem, ExpansionText) escreve §14.9.5 /E, a expansão da abreviação lida por leitores de tela no lugar de um acrônimo ('NASA' → 'National Aeronautics and Space Administration') e o valor coletado pela extração de conteúdo. THotPDF.SetStructureElementTitle (Elem, Title) escreve §14.7.5.2 /T, o título legível que distingue o elemento de elementos irmãos com a mesma função na árvore de estrutura (o painel de tags do Acrobat exibe /T ao lado do nome da função). Todos os três são definidores simples com semântica de "não fazer nada" quando o valor é vazio, um valor nil-Elem gera um erro e são permitidos em todos os níveis de PDF/A e PDF/X, pois as chaves são metadados estruturais.

2026-05-22 Version 2.119.39

  • AcroForm: foram completados os gatilhos para campos de formulário: três novos auxiliares foram adicionados ao AttachFieldKeyStrokeAction (v2.119.37) para fechar PDF 1.7 §12.7.5.3 Tabela 246. THotPDF.AttachFieldFormatAction instala /AA /F (evento de formatação, acionado quando o valor de exibição do campo precisa ser reformatado após um commit — uso típico é aplicar máscaras de moeda, data ou separador de milhares via AFNumber_Format / AFDate_FormatEx). THotPDF.AttachFieldValidateAction instala /AA /V (evento de validação, acionado após o usuário confirmar um novo valor — uso típico é verificar a faixa ou validar a entrada por meio de regex via event.rc := false). THotPDF.AttachFieldCalculateAction instala /AA /C (evento de cálculo, acionado quando qualquer campo de dependência é alterado de acordo com a ordem de cálculo do Catálogo /AcroForm /CO — uso típico é calcular totais ou impostos). Os quatro wrappers compartilham a mesma pesquisa FFormFields /T, semântica de substituição idempotente de última chamada e proteções JavaScript PDF/A + PDF/X. Outras chaves de gatilho no mesmo dicionário /AA (gatilhos de anotação /E /X /D /U /Fo /Bl e os três gatilhos de campos de formulário relacionados) são preservadas inalteradas. Refatoração interna: AttachFieldKeyStrokeAction agora delega a um auxiliar compartilhado _InstallFieldTriggerJSAction; os chamadores existentes da v2.119.37 verão mensagens de exceção idênticas em bytes.

2026-05-22 Version 2.119.38

  • RegisterUnicodeTTF agora captura as correspondências de ponto de código para glifo do Plano Multilíngue Suplementar (SMP, U+10000-U+10FFFF) a partir da subtabela de formato 12 do cmap da fonte carregada. Versões anteriores descartavam silenciosamente as entradas do SMP porque a pesquisa de ponto de código para glifo era um array de tamanho BMP; a v2.119.38 adiciona uma lista esparsa paralela (FUnicodeCpToGidSMP) que é preenchida junto com o array BMP. O novo método público GetUnicodeGlyphForCodepoint(Cp) retorna o ID do glifo para qualquer ponto de código Unicode até U+10FFFF (realiza uma busca binária na lista SMP para pontos de código acima do BMP), ou 0 (.notdef) quando o ponto de código não está mapeado no cmap da fonte carregada. Esta é uma funcionalidade adicional: o pipeline de codificação hexadecimal do lado do produtor, o fluxo /CIDToGIDMap e o ToUnicode CMap permanecem ancorados no BMP, portanto, escrever um caractere SMP em um fluxo de texto PDF ainda requer que os chamadores emitam pares substitutos UTF-16BE. A emissão completa de fluxo de texto com suporte a substitutos está reservada para uma revisão futura. Fontes que suportam apenas o formato 4 recebem uma lista SMP vazia, como esperado.

2026-05-22 Version 2.119.37

  • Novo utilitário para disparar ações com base em pressionamentos de tecla em formulários AcroForm: `THotPDF.AttachFieldKeyStrokeAction(FieldName, JavaScriptBody)` localiza o widget de formulário especificado pelo seu valor /T e instala uma ação JavaScript /AA /K para que os leitores de PDF executem o script a cada pressionamento de tecla durante a entrada de texto. Casos de uso incluem validação de entrada em tempo real (numérica, de data, regex), mascaramento de entrada e atualizações de campos calculados acionadas por edições em outro campo. Este utilitário é idempotente: chamadas repetidas substituem a entrada /K, preservando quaisquer outras chaves de disparo já presentes no dicionário /AA (formato /F, validação /V, recálculo /C, desfoque /Bl, foco /Fo, etc.). Todos os níveis de PDF/A (ISO 19005-1 §6.6.1, -2/-3 §6.5.1) e todos os níveis de PDF/X (ISO 15930 de pré-impressão) proíbem ações JavaScript, portanto, o utilitário gera um erro imediatamente com a referência da especificação relevante quando qualquer sinal de conformidade estiver presente. Baseado no dicionário de eventos de disparo PDF 1.7 §12.6.3 e na chave /K do campo de formulário da Tabela 246 §12.7.5.3.

2026-05-22 Version 2.119.36

  • BeginTaggedContent agora aceita quatro propriedades opcionais de sequência de conteúdo marcado da Tabela 322, §14.8.4 da especificação PDF 1.7 (Lang / Alt / ActualText / ExpansionText) e as emite como um único dicionário de propriedades BDC inline, juntamente com a entrada MCID existente. Lang contém a tag de linguagem natural BCP-47 para o trecho (usada por leitores de tela e extração de texto com reconhecimento de idioma); Alt é a descrição alternativa para trechos não textuais ou decorativos; ActualText é o texto de substituição usado pela extração de conteúdo e pela cópia e colagem, substituindo a sequência de glifos visível (essencial para ligaduras e glifos estilizados, onde o caractere visível difere do texto semântico subjacente); ExpansionText contém a chave /E que expande abreviações. Parâmetros vazios ignoram a entrada correspondente, de modo que o dicionário inline contenha apenas as chaves que o chamador preenche explicitamente, e o caminho de chamada legado com dois argumentos permanece idêntico em bytes à saída v2.119.35. O escape de strings literais PDF (parênteses e barra invertida) é automático; para payloads não ASCII (ActualText em CJK, Alt em Indic, etc.), os chamadores pré-codificam seus bytes como UTF-16BE com o BOM U+FEFF e empacotam o resultado no argumento AnsiString. A API de nível inferior correspondente BeginMarkedContentMCIDProps também é exposta para chamadores que precisam de controle direto do BDC, sem a estrutura de StructElem de alto nível.

2026-05-22 Version 2.119.35

  • O conjunto de caracteres "Arabic Extended-A" agora inclui um subconjunto de 9 letras persas/urdu que participam do formador de quatro posições no lado do produtor, versão v2.85.0. Com o "AutoShapeArabic" ativado, as seguintes letras são mapeadas para seus glifos "Arabic Presentation Forms-A" correspondentes (U+FB50-U+FBFF) com base no mesmo algoritmo de contexto de junção usado para o bloco árabe básico: PEH U+067E, TCHEH U+0686, JEH U+0698, KEHEH U+06A9, GAF U+06AF, FARSI YEH U+06CC (núcleo persa), além de TTEH U+0679, DDAL U+0688, RREH U+0691 (núcleo retroflexo urdu). As letras com junção dupla exibem o conjunto completo de formas isoladas/finais/iniciais/mediais; as letras com junção à direita (JEH / DDAL / RREH) exibem apenas as formas isoladas/finais, conforme o modelo de formação árabe. Outras letras "Arabic Extended-A" (ALEF WASLA U+0671, NOON GHUNNA U+06BA, variantes de HEH U+06C0-U+06C3, suplemento árabe completo U+0750-U+077F) permanecem como passagem direta e serão tratadas em uma revisão futura. O texto árabe que não é persa/urdu permanece idêntico em bytes à saída da versão v2.119.34.

2026-05-22 Version 2.119.34

  • O tratamento de nomes em arquivos PDF agora decodifica as sequências de escape ISO 32000-1 #XX ao importar ou copiar objetos PDF. Os nomes de recursos, os nomes de cores especiais, os nomes de funções estruturais e outros objetos de nome, como /PANTONE#20216#20CVC, agora são processados pelo HotPDF, mantendo seus valores de byte originais, em vez de serem copiados de volta com um caractere de número duplo.

2026-05-22 Version 2.119.33

  • O tratamento de datas em PDF agora segue mais de perto as regras de string de data da ISO 32000-1. As informações do documento, as datas derivadas do XMP e os carimbos de data/hora de assinatura usam o `TDateTime` fornecido pelo chamador, em vez de substituir silenciosamente pela hora atual, enquanto o analisador aceita campos de data opcionais padrão e sufixos de fuso horário sem corromper os campos de data/hora locais.
  • O filtro de importação de PDF agora possui funções auxiliares explícitas para ASCIIHexDecode, ASCII85Decode e RunLengthDecode, e o valor padrão de EarlyChange para LZWDecode agora corresponde ao padrão do PDF, que é 1. Isso melhora a compatibilidade com páginas importadas ou copiadas que utilizam filtros de fluxo PDF legados.

2026-05-21 Version 2.119.32

  • A ligadura obrigatória LAM-ALEF do árabe agora é implementada no módulo de formatação do lado do servidor, versão v2.85.0. Com o AutoShapeArabic ativado, qualquer sequência de U+0644 LAM (na forma original ou em qualquer uma de suas quatro formas formatadas, FEDD-FEE0) seguida por uma das quatro variantes de ALEF (MADDA U+0622, HAMZA-superior U+0623, HAMZA-inferior U+0625, simples U+0627; nas formas original ou formatada) é convertida em um único glifo de ligadura do bloco U+FEF5-U+FEFC. A forma de ligadura conectada versus isolada é selecionada com base em se o LAM foi formatado para uma forma final (FEDE) ou medial (FEE0) pelo algoritmo de quatro posições. Outras ligaduras obrigatórias do árabe (Allah U+FDFB e ligaduras decorativas) ainda exigem um motor GSUB completo e estão fora do escopo do modelo de formatação de tabela estática. O texto que não contém LAM-ALEF e as chamadas com AutoShapeArabic desativado permanecem idênticos à saída da versão v2.119.31. Três utilitários Unicode AcroForm /AP (linha única, multilinha, combinação) herdam automaticamente a alteração por meio do ponto de entrada compartilhado _ApplyArabicShaping.

2026-05-21 Version 2.119.31

  • Novo adaptador de exportação do sistema ExpressPrinting da DevExpress: dxHotPDFExportReportLinkToFile / dxHotPDFExportReportLinkToStream aceitam qualquer TBasedxReportLink (a família de links abstratos que conecta cxGrid / cxRichEdit / cxScheduler / cxPivotGrid e componentes semelhantes que podem ser impressos ao TdxComponentPrinter) e enviam cada página renderizada para o HotPDF em vez do emissor dxPSExportToPDF da DevExpress. O adaptador espelha o loop de exportação interno da DevExpress: ReconstruirRelatório → para cada página → DesenharPágina em um TMetafileCanvas → ExibirMetafileAprimorado no HotPDF. As opções expostas incluem Título / Autor / Assunto / Palavras-chave / PDFVersion / Compressão / RenderDPI. Possui as mesmas limitações de ponte de metaarquivo dos adaptadores FastReport / QuickReport / ReportBuilder: sem campos AcroForm, sem esboços, sem suporte a PDF/A / PDF/X. O adaptador está localizado em Lib/Addons/DevExpress/ e não está incluído no arquivo HotPDF*.dpk principal.

2026-05-20 Version 2.119.30

  • Nova classe de dispositivo ReportBuilder: TppHotPDFDevice herda de TppGraphicsDevice, portanto, se encaixa na cadeia padrão de publicação → dispositivo do ReportBuilder quando atribuída a TppReport.PrinterDevice ou a TppPublisher.Device. Cada página é renderizada em um TMetafileCanvas temporário (criado em BeforeRenderPage e finalizado em AfterRenderPage), capturada como um TMetafile e roteada através do importador EMF do HotPDF (HPDFEmf.ShowEnhancedMetafile). As propriedades expõem Título / Autor / Assunto / Palavras-chave / PDFVersion / CompressionLevel / Compressed; SetOutputStream direciona os bytes PDF para um TStream fornecido pelo chamador. Possui as mesmas limitações da ponte de metaarquivo dos adaptadores FastReport / QuickReport: sem campos AcroForm, sem esboços, sem suporte a PDF/A / PDF/X. O adaptador está localizado em Lib/Addons/ReportBuilder/ e não está incluído no arquivo HotPDF*.dpk principal.

2026-05-20 Version 2.119.29

  • Novo filtro de exportação QuickReport: `TQRHotPDFExportFilter` herda de `TQRExportFilter`, portanto, integra-se ao fluxo de trabalho regular `MyReport.ExportToFilter(MyFilterInstance)` sem alterações no núcleo do QuickReport. O adaptador coleta os metarquivos por página que o QuickReport já armazena em `QRPrinter.PageList` e alimenta cada um através do importador EMF do HotPDF (`HPDFEmf.ShowEnhancedMetafile`). As propriedades expõem Título, Autor, Assunto, Palavras-chave, Versão do PDF, Nível de Compressão e Compactado; `SetOutputStream` direciona os bytes do PDF para um objeto `TStream` fornecido pelo chamador, em vez de para o disco. Possui as mesmas limitações de ponte de metarquivo do adaptador FastReport: sem campos AcroForm, sem esboços, sem suporte a PDF/A ou PDF/X. O adaptador está localizado em `Lib/Addons/QuickReport/` e não está incluído no arquivo principal `HotPDF*.dpk`.

2026-05-20 Version 2.119.28

  • Novo adaptador de exportação FastReport 4 / FastReport VCL: `TfrxHotPDFExport` herda de `TfrxCustomExportFilter`, portanto, integra-se ao fluxo de trabalho regular `MyReport.Export(MyExportInstance)` sem alterações no núcleo do FastReport. O adaptador direciona cada página preparada para o importador EMF do HotPDF (através de `TfrxPreviewPages.DrawPage` do FastReport → `TMetafileCanvas` → `HotPDF.ShowEnhancedMetafile`), preservando o conteúdo vetorial e raster da página renderizado pelo mecanismo de layout padrão do FastReport, sem a necessidade de código de emissão por objeto. As propriedades expõem `Title`, `Author`, `Subject`, `Keywords`, `PDFVersion`, `CompressionLevel` e `RenderDPI` para controlar o PDF resultante. Limitações: não suporta campos AcroForm, nem outlines, nem perfis PDF/A / PDF/X (estes requerem um pipeline de emissão por objeto, planejado para uma revisão futura). O adaptador é distribuído em `Lib/Addons/FastReport4/` e NÃO está incluído no arquivo `HotPDF*.dpk` principal; os usuários devem adicioná-lo ao seu próprio projeto, juntamente com o pacote FastReport correspondente.

2026-05-20 Version 2.119.27

  • Novo sistema de assinatura de PDF baseado em PFX: THotPDF.SignPDFWithPFX(InputPDFPath, OutputPDFPath, PFXFilePath, Password) carrega um PDF não assinado que já contém um espaço reservado para o campo de assinatura, analisa o arquivo PFX / PKCS#12, cria uma estrutura CMS SignedData (RFC 5652) completa sobre os bytes cobertos pelo intervalo de bytes e grava o PDF assinado em uma única chamada. Uma versão alternativa baseada em TStream também é fornecida para fluxos de trabalho em memória. O espaço alocado para o conteúdo do PDF deve ser grande o suficiente para armazenar o código hexadecimal DER do CMS; o padrão de 8192 bytes é suficiente para RSA de 1024/2048 bits. Apenas arquivos PFX com PBES2 + AES-256-CBC são suportados (devido ao limite do analisador PKCS#12 da versão v2.119.26).
  • Nova unidade HPDFCMS: construtor de dados assinados CMS. HPDFCMSBuildSignedData compõe ContentInfo → SignedData → SignerInfo com conteúdo separado id-data, atributos assinados (contentType + messageDigest + signingTime, ordenados por DER ascendente conforme RFC 5652 §5.4), identificador de signatário IssuerAndSerialNumber extraído do certificado X.509, algoritmo de assinatura RSA + SHA-256 e o certificado X.509 envolvido em [0] certificados IMPLÍCITOS. Também expõe HPDFCMSSHA256ByteRanges para digesto de duas janelas em fluxo e HPDFCMSBytesToHex para injeção de placeholder /Contents. Fecha a pilha de assinatura interna iniciada com HPDFASN1 (v2.119.23) + HPDFRSA (v2.119.24) + extensões HPDFCrypt (v2.119.25) + HPDFPFX (v2.119.26).

2026-05-20 Version 2.119.26

  • Nova unidade HPDFPFX: analisador de contêiner PKCS#12 / PFX. Lê arquivos .pfx / .p12 do OpenSSL ≥ 3.0, certutil do Windows 11+ e Keychain Access do macOS, descriptografa as cargas úteis SafeBag PBES2 (PBKDF2-HMAC-SHA-256 + AES-256-CBC) e extrai os parâmetros da chave privada RSA e do certificado X.509 no formato DER. Retorna um registro THPDFPFXKeyMaterial com CertDER, Modulus, PublicExponent e PrivateExponent, que o código de assinatura CMS subsequente pode consumir diretamente. Uma senha incorreta é detectada através da falha de preenchimento PKCS#7 que ocorre após uma chave AES inválida. Arquivos PBE-SHA1-3DES legados geram um aviso claro para reexportar usando `-keypbe AES-256-CBC -certpbe AES-256-CBC`.

2026-05-20 Version 2.119.25

  • Novas primitivas de criptografia: cifra inversa AES-256 com AES256DecryptBlock + AES256CBCDecryptPKCS7 + AES256CBCDecryptNoPad (complementando os utilitários de criptografia existentes, conforme FIPS-197 §5.3), HMAC-SHA-256 (RFC 2104) e PBKDF2-HMAC-SHA-256 (RFC 8018 §5.2). Verificado em relação aos vetores HMAC do RFC 4231 e às saídas de referência padrão do PBKDF2-SHA-256. Juntamente com o decodificador ASN.1 da versão 2.119.23 e as primitivas RSA da versão 2.119.24, isso completa a base criptográfica necessária para o caminho de descriptografia PBES2-AES-256 SafeBag usado em arquivos PKCS#12 / PFX modernos (OpenSSL ≥ 3.0 / Windows 11+).

2026-05-20 Version 2.119.24

  • Nova unidade HPDFRSA: aritmética de inteiros de precisão múltipla + exponenciação modular RSA + codificação EMSA PKCS#1 v1.5. Suficientemente grande para assinar com chaves RSA de 2048/4096 bits do mundo real. Juntamente com o decodificador ASN.1 da versão v2.119.23, isso completa os primitivos criptográficos necessários para o pipeline de assinatura de PDF baseado em PFX que está por vir. Nenhuma API voltada para o usuário usa isso ainda — é uma infraestrutura interna que aguarda as camadas PKCS#12 + CMS.

2026-05-20 Version 2.119.23

  • Nova unidade HPDFASN1: um decodificador BER/DER compacto para o subconjunto ASN.1 que o HotPDF precisa para ler keystores PKCS#12, certificados X.509 e contêineres CMS/PKCS#7 SignedData. Expõe THPDFASN1Node (descritor Tag-Length-Value analisado), THPDFASN1ParseNode e métodos de acesso ParseAt, Content, ToInteger, ToBigInt, ToOID, ToString, e iteradores FirstChild, NextSibling, Children. Rejeita explicitamente a forma BER de comprimento indefinido e codificações com números de tag altos (>= 31), espelhando o subconjunto estrito do DER. Esta é uma infraestrutura interna para o pipeline de assinatura PFX que será integrado na biblioteca em versões futuras — nenhuma API voltada para o usuário depende dela ainda.

2026-05-20 Version 2.119.22

  • Novas sobrecargas para as anotações PolyLine e Polygon com metadados completos: THPDFPage.AddPolylineAnnotation e AddPolygonAnnotation ganham duas novas sobrecargas que aceitam um array de vértices THPDFCurrPoint e um registro THPDFPolyExtras opcional. O registro extras expõe as entradas opcionais da ISO 32000-1 §12.5.6.9, como /IC (cor interna), /BE (borda esfumaçada, com opções de solidez/esfumaçado e intensidade /I), /IT (intenção: PolyLineDimension, PolyLineFlight, PolygonCloud, PolygonDimension) e /LE (estilos de terminação de linha) para PolyLine. Use HPDFDefaultPolyExtras() para inicializar o registro. As novas sobrecargas validam que pelo menos dois vértices sejam fornecidos e incrementam automaticamente a versão do documento (PDF 1.5 / 1.6 / 1.7, dependendo da intenção). As sobrecargas anteriores, que intercalam Single, continuam a compilar sem alterações.

2026-05-20 Version 2.119.21

  • Novas opções para a anotação de Linha: A função `AddLineAnnotation` recebe uma terceira sobrecarga que aceita um registro `THPDFLineExtras` para controlar as entradas opcionais da Tabela 175, seção §12.5.6.7 do PDF 1.6/1.7 — como a cor interna (/IC) para setas e diamantes preenchidos, o comprimento da linha guia (/LL), a extensão da linha guia (/LLE), o deslocamento da linha guia (/LLO, PDF 1.7), a flag de legenda (/Cap) com o posicionamento (/CP, /Inline ou /Top, PDF 1.7) e o deslocamento da legenda (/CO), e a intenção da linha (/IT, LineArrow / LineDimension). Use `HPDFDefaultLineExtras()` para iniciar com um registro inicializado em zero. A nova sobrecarga atualiza automaticamente a versão do documento para PDF 1.6 (ou 1.7 quando /LLO, /CP e /CO são solicitados). As duas sobrecargas anteriores continuam a gerar a mesma saída em bytes, e apenas as entradas que o chamador realmente solicita são escritas.

2026-05-20 Version 2.119.20

  • Novas ações de botões "baShow" e "baImportData": THPDFButtonAction agora inclui "baShow" (um espelho de "baHide" que emite "/H false" para exibir novamente um widget oculto) e "baImportData" (/S /ImportData /F filespec para carregar dados de formulário FDF ao clicar, ISO 32000-1 §12.7.5.4). "baShow" é permitido de acordo com as especificações para PDF/A e PDF/X; "baImportData" é bloqueado em ambos, de acordo com a ISO 19005-1 §6.6.1 e a ISO 15930 para pré-impressão, respectivamente.
  • Nova sobrecarga de "Ocultar/Mostrar" para múltiplos campos: THPDFPage.AddPushButtonWithHideAction(FieldName, Caption, Targets, Hide, Rectangle, Flags) aceita um array de nomes de campos de destino e um valor booleano "Hide" explícito, permitindo que um único botão alterne a visibilidade de vários widgets com um único clique. Um array "Targets" vazio gera um erro. Tanto PDF/A quanto PDF/X suportam esta sobrecarga (apenas a visibilidade de widgets).

2026-05-20 Version 2.119.19

  • Novo controle de usuário SubmitForm /Flags: THPDFPage.AddPushButtonWithSubmitAction(FieldName, Caption, URL, Rectangle, SubmitFlags) expõe o conjunto completo de flags da Tabela 237 da seção ISO 32000-1 §12.7.5.2, através do novo tipo THPDFSubmitFormFlags. Os chamadores agora podem combinar sffExportFormatHTML / sffXFDF / sffSubmitPDF (formato de envio), sffGetMethod (HTTP GET vs POST), sffIncludeAnnotations, sffSubmitCoordinates, sffCanonicalFormat, sffIncludeNoValueFields, sffIncludeAppendSaves, sffExclNonUserAnnots, sffEmbedForm e outros, substituindo o /Flags 0 (FDF + POST) codificado no caminho legado AddPushButtonWithAction(.., baSubmitURL, ..). O método existente AddPushButtonWithAction(.., baSubmitURL, ..) continua a emitir /Flags 0 para compatibilidade com versões anteriores no nível de bytes. As mesmas restrições PDF/A / PDF/X se aplicam ao baSubmitURL: permitido em PDF/A, bloqueado em PDF/X.

2026-05-20 Version 2.119.18

  • Tipos de ações de botão estendidos: THPDFButtonAction agora inclui baNamed e baHide. baNamed emite uma ação /S /Named /N (ISO 32000-1 §12.6.4.11) adequada para os quatro comandos de navegação padrão: NextPage / PrevPage / FirstPage / LastPage (PDF/A permite todos os quatro, conforme ISO 19005-1 §6.6.1) e extensões do Acrobat, como Print e SaveAs. baHide emite uma ação /S /Hide /T /H true (§12.6.4.10) que oculta o campo de formulário nomeado quando o botão é clicado. Ambos os tipos de ação são permitidos de acordo com as especificações do PDF/A e PDF/X; apenas baJavaScript / baResetForm / baSubmitURL mantêm suas restrições de conformidade existentes.

2026-05-20 Version 2.119.17

  • Novo registro de destinos nomeados: THotPDF.RegisterNamedDestination(Name, PageIndex, FitMode, ...) registra um destino simbólico na árvore de nomes do Catálogo /Names /Dests (ISO 32000-1 §12.3.2.3). As ações GoTo / GoToR e as entradas de esboço /Dest podem então referenciar um destino por nome em vez de codificar números de página, o que mantém as referências cruzadas estáveis ​​durante a inserção/exclusão/reorganização de páginas. O novo enum THPDFDestinationFitMode cobre todas as oito opções de ajuste especificadas (XYZ, Fit, FitH, FitV, FitR, FitB, FitBH, FitBV). O método gera um erro se o Nome estiver vazio, o PageIndex estiver fora do intervalo ou o Nome for duplicado; ele também atualiza automaticamente a versão do documento para PDF 1.2, quando necessário. Não há restrições para PDF/A / PDF/X — os recursos de navegação são permitidos em todos os perfis.

2026-05-20 Version 2.119.16

  • Novas opções de estilo de final de linha para anotações de linha /LE: THPDFPage.AddLineAnnotation agora possui uma sobrecarga que aceita estilos de final de linha de início/fim. O conjunto completo da Tabela 176 da seção ISO 32000-1 §12.5.6.7 é exposto através do novo enum THPDFLineEndingStyle: None, Square, Circle, Diamond, OpenArrow, ClosedArrow, Butt, ROpenArrow, RClosedArrow, Slash. As anotações de linha agora podem ser renderizadas como setas adequadas, marcadores de dimensionamento ou indicadores dentro do Adobe Acrobat / Foxit, sem que o host precise desenhar manualmente as pontas das setas na página. A sobrecarga antiga de quatro parâmetros ainda funciona de forma idêntica.

2026-05-20 Version 2.119.15

  • Novo estilo para a estrutura (marcador): THPDFDocOutlineObject agora expõe as propriedades Cor, Negrito e Itálico (ISO 32000-1 §12.3.3 Tabela 153 /C e /F). O painel da estrutura agora pode render marcadores em cores e com ênfase em negrito ou itálico, o que é útil para agrupar capítulos, marcar seções incompletas ou que precisam de atenção e para corresponder ao estilo da marca. A cor padrão é clNone (nenhum registro /C é emitido, idêntico ao resultado anterior); Negrito e Itálico são padrão como falso. Definir as propriedades após AddChild atualiza o dicionário da estrutura em tempo real, e definir a Cor de volta para clNone ou tanto Negrito quanto Itálico para falso remove as entradas /C e /F.

2026-05-20 Version 2.119.14

  • Novo registro de JavaScript nomeado no nível do documento: THotPDF agora expõe RegisterDocumentJavaScript(Name, Body). Cada entrada registrada é serializada na árvore de nomes do Catálogo /Names /JavaScript (ISO 32000-1 §7.7.4.4 + §12.6.4.16) como um dicionário indireto /S /JavaScript /JS. As ações de widgets do AcroForm e as ações de abertura do documento podem invocar a função registrada por nome através do mecanismo JavaScript do visualizador (Acrobat, Foxit). Útil para compartilhar uma biblioteca de funções auxiliares de validação, formatação ou cálculo em vários widgets, sem duplicar o código JS em cada dicionário /A. Este método é rejeitado em qualquer nível de conformidade PDFA (ISO 19005-1 §6.6.1) e em qualquer nível de conformidade PDFX (ISO 15930 fluxos de trabalho de pré-impressão), e rejeita nomes ou conteúdos vazios, bem como registros de nomes duplicados.

2026-05-20 Version 2.119.13

  • Novo suporte para miniaturas de página: THPDFPage agora expõe SetPageThumbnail(ImageIndex) e ClearPageThumbnail. Visualizadores de PDF (Acrobat, Foxit, visualizadores de navegador) usam a entrada /Thumb da página (ISO 32000-1 §12.3.4) para renderizar uma visualização pré-gerada em seu painel de navegação, sem rasterizar a página, o que é especialmente útil para arquivos com muitas imagens, onde o rasterizador do visualizador seria lento. A função auxiliar reutiliza qualquer imagem registrada através de AddImage / AddImageFromFile, permitindo que os chamadores preparem um bitmap de visualização redimensionado e o anexem com uma única chamada; SetPageThumbnail(-1) ou ClearPageThumbnail remove uma miniatura anexada anteriormente. Índices de imagem fora do intervalo geram uma exceção descritiva.

2026-05-20 Version 2.119.12

  • Correção de conformidade com PDF/A: Agora, a função AddPushButtonWithAction gera um erro quando os tipos de ação baJavaScript ou baResetForm são usados em qualquer nível de conformidade PDFA (PDF/A-1/2/3). As normas ISO 19005-1 §6.6.1 / ISO 19005-2 §6.5.1 / ISO 19005-3 §6.5.1 proíbem as ações JavaScript, ResetForm e ImportData em todos os níveis de PDF/A. As ações baSubmitURL (SubmitForm), baURI e baNone permanecem permitidas no PDF/A — SubmitForm está na lista de ações permitidas da seção §6.6.1. Anteriormente, os botões podiam conter ações proibidas, mesmo com o PDFACompliance habilitado, pois a proteção da versão v2.119.54 cobria apenas os caminhos Catalog /AA e OpenAction no nível do documento.
  • Correção de conformidade com PDF/X: Agora, a função AddPushButtonWithAction gera um erro quando os tipos de ação baJavaScript, baResetForm ou baSubmitURL são usados em qualquer nível de conformidade PDFX. Os fluxos de trabalho de pré-impressão ISO 15930 excluem a execução de scripts interativos, a modificação de formulários e o envio de formulários para endpoints externos.

2026-05-20 Version 2.119.11

  • Correção de conformidade com PDF/A: os tipos de anotação PDF/A agora impedem a conclusão. As funções AddScreenAnnotation, Add3DAnnotation e AddRichMediaAnnotation agora geram erros quando PDFACompliance está habilitado em qualquer nível (PDF/A-1/2/3). As normas ISO 19005-1 §6.5.2 / ISO 19005-2 §6.6.1 / ISO 19005-3 §6.6.1 proíbem os subtipos de anotação Screen, 3D e RichMedia (multimídia / Extensão Adobe Nível 3) em todos os níveis PDF/A. As mesmas restrições são aplicadas em PDFXCompliance — os fluxos de trabalho de pré-impressão da norma ISO 15930 rejeitam os subtipos de multimídia.
  • Correção de conformidade com PDF/A-1: `AddWatermarkAnnotation` e `AddRedactAnnotation` agora geram erros quando `PDFACompliance` está definido como PDF/A-1. As anotações de marca d'água (PDF 1.6) e de redação (PDF 1.7) são subtipos de anotações incompatíveis com a base PDF 1.4 do PDF/A-1 (ISO 19005-1 §6.5.2). O PDF/A-2 e o PDF/A-3 (base PDF 1.7) continuam a permitir ambos os tipos de anotação.

2026-05-20 Version 2.119.10

  • Correção de conformidade com PDF/A: `AddImageWithSMask` e `AddImageWithSMask32` agora geram um erro quando `PDFACompliance` está definido como PDF/A-1. A ISO 19005-1:2005 §6.4 proíbe todos os efeitos de transparência; um fluxo /SMask de imagem ativa a composição de transparência de máscara suave. Pré-combine a imagem em uma cor de fundo e passe o resultado para `AddImage()`, ou use PDF/A-2 ou posterior para suporte à transparência. PDF/A-2 e PDF/A-3 continuam a permitir a transparência de máscara suave de imagem.

2026-05-20 Version 2.119.9

  • Correção de conformidade com PDF/A: `SetTransparencyGroup` e `SetTransparencyGroupICC` agora geram um erro quando `PDFACompliance` é definido como PDF/A-1. A ISO 19005-1:2005 §6.4 proíbe todos os efeitos de transparência; os grupos de transparência no nível da página (dicionário `/Group /S /Transparency` na página) ativam o modelo de composição de transparência para toda a página, o que é uma violação direta da §6.4. PDF/A-2 e PDF/A-3 continuam a permitir grupos de transparência na página.

2026-05-20 Version 2.119.8

  • Correção de conformidade PDF/A: RegisterHalftoneState agora gera um erro quando PDFACompliance está ativo e um dicionário de meio-tons personalizado é fornecido (ou seja, HTDefaultName = false). As normas ISO 19005-1:2005 §6.2.9 e ISO 19005-2:2011 / ISO 19005-3:2012 §6.3.7 permitem apenas o literal de nome "/Default" para ExtGState /HT; dicionários de meio-tons personalizados (tipos 1, 5, 6, 10, 16) são proibidos. Passar HTDefaultName=True para redefinir para o meio-tom padrão continua a funcionar em todos os níveis PDF/A.
  • Correção de conformidade com PDF/A: RegisterSoftMaskState agora gera um erro quando PDFACompliance está definido como PDF/A-1 e um dicionário de máscara suave personalizado é fornecido (parâmetro SMaskDict). A ISO 19005-1:2005 §6.4 proíbe todos os efeitos de transparência; um valor /SMask diferente de None ativa a transparência da máscara suave. Ainda é permitido passar SMaskNone=True para redefinir as máscaras suaves. PDF/A-2 e PDF/A-3 continuam a permitir a transparência da máscara suave.

2026-05-20 Version 2.119.7

  • Correção de conformidade PDF/A: AddDocumentAttachment (incorporação de arquivos no nível do documento via Catalog /Names /EmbeddedFiles) agora gera um erro quando PDFACompliance está ativo para PDF/A-1 ou PDF/A-3. A norma ISO 19005-1:2005 §6.1.11 proíbe explicitamente a chave /EmbeddedFiles no dicionário Names do documento no modo PDF/A-1. Para PDF/A-3, os anexos de documentos devem ser registrados através de AddPDFA3AssociatedFile() para incluir o array /AF e a chave /AFRelationship obrigatórios, conforme a norma ISO 19005-3:2012, Anexo E. O PDF/A-2 continua a permitir anexos de documentos, desde que os arquivos anexados sejam eles próprios conformes ao padrão PDF/A.

2026-05-20 Version 2.119.6

  • Correção de conformidade com PDF/A: ao usar fontes padrão (Arial, Helvetica, Times New Roman, Courier New, Symbol, ZapfDingbats) com a opção StandardFontEmulation habilitada, agora é gerada uma exceção descritiva quando o PDFACompliance está ativo. As seções §6.3 da ISO 19005-1:2005 e §6.3 da ISO 19005-2:2011 / ISO 19005-3:2012 exigem que todas as fontes sejam incorporadas em arquivos compatíveis; o caminho de emulação de fontes padrão emite uma referência a uma fonte não incorporada, o que é uma violação direta da seção §6.3. Os usuários devem definir StandardFontEmulation := false ou usar RegisterUnicodeTTF() com os arquivos de fonte reais para a saída PDF/A.
  • Correção de conformidade com PDF/A: fontes não padronizadas são agora sempre incorporadas quando o PDFACompliance está ativo, independentemente da configuração da propriedade FontEmbedding. A otimização FontEmbedding = false é silenciosamente ignorada no modo PDF/A para atender ao requisito de que todas as fontes sejam incorporadas, conforme especificado na seção §6.3.

2026-05-20 Version 2.119.5

  • Correção de conformidade com PDF/A: as ações JavaScript e os elementos /AA (Ações Adicionais) no nível do catálogo agora são bloqueados quando o PDFACompliance está ativo. As seções ISO 19005-1:2005 §6.6.1/§6.6.2 e ISO 19005-2:2011 / ISO 19005-3:2012 §6.5.1/§6.6.2 proíbem todos os tipos de ações JavaScript e proíbem a chave /AA no dicionário do catálogo. Chamar SetActionScript com qualquer valor de PDFACompliance agora gera uma exceção descritiva. Como uma medida de segurança adicional, os caminhos de emissão de JavaScript OpenAction e Catalog /AA em EndDoc também são controlados para ignorar silenciosamente a saída quando o PDFACompliance está ativo, garantindo que nenhuma chave não compatível seja escrita, mesmo por meio de caminhos internos.

2026-05-20 Version 2.119.4

  • Correção de conformidade com PDF/A: o valor de AcroForm /NeedAppearances é agora forçado para falso quando o PDFACompliance está ativo, independentemente da configuração de AutoFormAppearances. As seções 6.9 da ISO 19005-1:2005 e 6.4 da ISO 19005-2:2011 / ISO 19005-3:2012 exigem que essa chave esteja ausente ou definida como falso em arquivos compatíveis. Anteriormente, se AutoFormAppearances estivesse desativado enquanto PDFACompliance estivesse ativo, /NeedAppearances seria definido como verdadeiro, resultando em um arquivo não compatível.

2026-05-20 Version 2.119.3

  • Correção de conformidade com PDF/A: os subconjuntos de CIDFont incorporados agora incluem um fluxo /CIDSet em seu FontDescriptor quando o PDFACompliance está ativo. As seções ISO 19005-1:2005 §6.3.5 e ISO 19005-2:2011 / ISO 19005-3:2012 §6.2.11 exigem que os subconjuntos de CIDFont contenham um fluxo de bits /CIDSet que indica quais valores CID estão presentes no programa de fonte incorporado. O HotPDF usa a codificação Identity-H, onde o CID é igual ao ponto de código Unicode, portanto, o CIDSet é construído diretamente a partir do conjunto de pontos de código usados no documento. O fluxo de bits é compactado com FlateDecode e anexado ao FontDescriptor existente como um objeto de fluxo indireto. Isso corrige uma lacuna anteriormente não detectada em todos os níveis de PDF/A (a auditoria de conformidade anterior afirmava incorretamente que isso já estava implementado).

2026-05-20 Version 2.119.2

  • Correção da conformidade com PDF/A-2 e PDF/A-3: o dicionário de aparência de anotações (/AP /N) agora é emitido automaticamente para tipos de anotações que não são links e não são pop-ups (TextNotes, FreeText, Line, Square, Circle, Stamp, FileAttachment) quando PDFACompliance está definido para um nível PDF/A-2 ou PDF/A-3. A ISO 19005-2:2011 §6.3.3 e a ISO 19005-3:2012 §6.3.3 exigem que cada uma dessas anotações tenha pelo menos um dicionário de aparência (com a entrada N do tipo XObject). Um objeto XObject de formulário vazio é emitido para atender ao requisito estrutural; a maioria dos visualizadores de PDF usa sua própria renderização integrada para tipos de anotações padrão, independentemente do conteúdo do fluxo /AP. As anotações de link e pop-up são explicitamente isentas pela norma e permanecem inalteradas. Este requisito não se aplica ao PDF/A-1 (a ISO 19005-1 §6.5.3 restringe apenas o formato do /AP quando presente, não sua presença).

2026-05-20 Version 2.119.1

  • Correção de conformidade com PDF/A: todos os tipos de anotações que não são widgets (notas de texto, carimbos, linhas, formas, hiperlinks, links GoTo, links GoToR, links URI) agora definem automaticamente a flag /F Print (bit 3 = 1, valor 4) quando o PDFACompliance está ativo. As normas ISO 19005-1:2005 §6.5.3 e ISO 19005-2:2011 / ISO 19005-3:2012 §6.3.2 exigem que cada dicionário de anotação contenha uma chave /F com o bit Print definido. Anteriormente, apenas as anotações de widget (campos de formulário) tinham essa flag; todos os outros tipos de anotações a omitiam, o que tornava os arquivos gerados não conformes.
  • Correção de conformidade com PDF/A-1: grupos de conteúdo opcionais (camadas) agora são bloqueados quando PDFACompliance está definido para um nível PDF/A-1 ('A' ou 'B'). A norma ISO 19005-1:2005 §6.1.13 proíbe a chave /OCProperties no dicionário Catalog; chamar RegisterOptionalContentGroup sob PDF/A-1 agora gera uma exceção descritiva, orientando os usuários a usar PDF/A-2 ou posterior se o conteúdo opcional for necessário. A emissão de /OCProperties no final do documento também é bloqueada para evitar não conformidade silenciosa, mesmo que grupos de conteúdo opcionais tenham sido registrados.

2026-05-20 Version 2.119.0

  • Suporte a contêineres XAdES-in-PDF conforme ETSI EN 319 142-2 V1.2.0 §6.2 (encerramento da série B/C/D, parte 3). Incorpora os bytes XML assinados XAdES fornecidos pelo chamador como um PDF EmbeddedFile, registra o Filespec no array /AF do Catálogo e define /AFRelationship de acordo com a enumeração PDF 2.0 especificada pelo chamador. É apenas um wrapper no lado do produtor — a construção real da assinatura XAdES (XML-DSig + ETSI EN 319 132-1 QualifyingProperties + carimbo de data/hora RFC 3161 incorporado em xades:UnsignedSignatureProperties) é de responsabilidade da biblioteca criptográfica XML do chamador (Apache Santuario, .NET SignedXml, libxmlsec, Saxon com extensões XAdES, etc.).
  • Novo método `THotPDF.AddXAdESAssociatedFile(FileName, XMLBytes, Description, MimeType, Relationship)`. Valores padrão: MimeType `'application/xml'` (também comumente `'application/vnd.etsi.asic-e+zip'` para arquivos ASiC-E), Relationship `'Source'` (o XML assinado por XAdES é o conteúdo principal do documento). Retorna o dicionário Filespec indireto para que os chamadores possam anexar metadados adicionais ou referências cruzadas a partir de entradas de catálogo personalizadas.
  • Independentemente do PDF/A: ao contrário de `AddPDFA3AssociatedFile` na versão v2.108 (que exige PDFACompliance='3*'), esta função auxiliar não possui restrições relacionadas ao PDF/A — a inclusão de XAdES em PDF é uma família de perfis própria, conforme especificado em PAdES Part 2 V1.2.0 §6.
  • Correção de um bug crítico em `_EscapePDFNameBytes` (PDF 1.7 ISO 32000-1 §7.3.5 + Tabela 2). A função de escape anterior convertia apenas bytes fora do intervalo [0x21..0x7E] e o caractere '#'; os delimitadores PDF (`/ ( ) < > [ ] { } %`) são obrigatórios na especificação para serem escapados como `#XX` dentro dos nomes, mas estavam sendo deixados literais. Nomes como `/Subtype /application/xml` eram, portanto, analisados por leitores rigorosos como dois tokens de nome separados (/application seguido por /xml), o que impedia o reconhecimento de EmbeddedFile /Subtype. Na versão 2.119, todos os 10 delimitadores são escapados de acordo com a especificação; os nomes que não são delimitadores (a grande maioria das emissões do HotPDF) permanecem idênticos em bytes. Os tipos MIME do PDF/A-3 Anexo E (v2.108) agora são emitidos corretamente (`/application#2Fxml` em vez de `/application/xml` incorreto).
  • A série PAdES B/C/D foi finalizada em 3 commits: v2.117 (perfis estendidos E-BES / E-EPES / E-LTV conforme a Parte 2 §5) + v2.118 (valores iniciais conforme ISO 32000-1 §12.7.5.5 + Parte 2 §4.2.6) + v2.119 (XAdES-in-PDF + correção de escape de delimitadores conforme a Parte 2 §6.2). Combinado com as versões v2.109 a v2.116, o HotPDF agora cobre todo o escopo de produtores PAdES, incluindo perfis básicos, perfis estendidos, carimbo de data/hora do documento, informações de validação DSS, extensões ESIC, restrições de assinatura por meio de valores iniciais e contêiner XAdES-in-PDF.
  • Compilação limpa para Win32 e Win64; as versões base v2.108 a v2.118 foram recompiladas, sem alterações. Novos testes de verificação (smoke tests) para `smoke_pades_xades` incluem 2 caminhos positivos (XML assinado com XAdES como `/AFRelationship /Source` e arquivo ASiC-E como `/Data`) e 4 caminhos de rejeição (nome de arquivo vazio, bytes XML vazios, tipo MIME vazio, relação inválida). O verificador em Python percorre todos os arquivos, incluindo as formas de escape `/Subtype /application#2Fxml` e `/Subtype /application#2Fvnd.etsi.asic-e+zip`. Os testes de verificação para PDF/A-3, PAdES e PDF/X da versão v2.108 foram executados novamente e passaram com sucesso.

2026-05-20 Version 2.118.0

  • Valores de semente PAdES conforme 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 (etapa 2 de 3 da série B/C/D). Um dicionário de valor de semente (SV) anexado a um campo de assinatura restringe o que a ferramenta de assinatura do leitor pode escolher para esse campo específico — qual manipulador, qual SubFilter, qual método de digestão, se as informações de revogação são obrigatórias e qual versão mínima do PDF é necessária.
  • Novo método `THotPDF.AttachPAdESSeedValue(FieldName, SubFilters, DigestMethods, ForceSubFilter, ForceDigestMethod, AddRevInfo, MinPDFVersion, ForceMinPDFVersion)`. Ele procura o campo de assinatura nomeado na lista de campos do AcroForm (que deve ter sido criado anteriormente por uma chamada a `AddPAdESSignatureField` ou `AddDocumentTimestampSignature`) e anexa um sub-dicionário "/SV" com as restrições fornecidas pelo chamador.
  • Entradas de valor inicial emitidas (conforme a Tabela 234):
    • `/Type /SV`
    • `/SubFilter` array de nomes — por exemplo, [/ETSI.CAdES.detached]
    • `/DigestMethod` array de nomes — por exemplo, [/SHA256 /SHA384 /SHA512]
    • `/AddRevInfo` booleano — a ferramenta de assinatura deve incluir OCSP/CRL no CMS
    • `/V` número — versão mínima do PDF (por exemplo, 1.7)
    • `/Ff` flags inteiras (Tabela 235) — cada parâmetro Force* define o bit correspondente, portanto, a ferramenta de assinatura DEVE respeitar a restrição (bit 2 = força SubFilter, bit 3 = força V, bit 6 = força AddRevInfo, bit 7 = força DigestMethod)
  • Regras de conformidade com as especificações: O PAdES Part 2 V1.2.0 §4.2.6 proíbe valores de semente que forçariam as ferramentas de assinatura a violar o perfil PAdES (por exemplo, especificar o SubFilter PKCS#1). O HotPDF não impõe isso no lado do produtor; o chamador é responsável por passar apenas valores permitidos pela especificação (`'adbe.pkcs7.detached'` ou `'ETSI.CAdES.detached'` para SubFilter, SHA-256+ para DigestMethod). O comentário de documentação auxiliar especifica explicitamente essa restrição.
  • Compilação limpa para Win32 e Win64; todas as versões base de v2.108 a v2.117 foram recompiladas sem alterações. O novo módulo "smoke_pades_seedvalue" cria um campo PAdES-B-T e associa um conjunto completo de restrições de valor inicial (SubFilter restrito a ETSI.CAdES.detached, DigestMethod restrito a SHA256/384/512, AddRevInfo definido como verdadeiro, MinPDFVersion definido como 1.7, todos os bits de força definidos). O verificador em Python percorre o sub-dicionário /SV e verifica a estrutura de cada entrada; também testa o caminho de rejeição para "FieldName desconhecido".
  • Na versão 2.119, o passo 3 da série implementa o contêiner XAdES-in-PDF, conforme a Parte 2, versão 1.2.0, §6, finalizando a série B/C/D. No lado do produtor, isso é uma camada simples que utiliza a infraestrutura existente da HotPDF para EmbeddedFile e Catalog/AF (helper PDF/A-3 da versão 2.108), além da semântica /AFRelationship que o PAdES Parte 2, versão 1.2.0, §6.2.2, espera para payloads XML assinados com XAdES.

2026-05-20 Version 2.117.0

  • PAdES perfis estendidos conforme ETSI EN 319 142-2 V1.2.0 §5 (série B/C/D, etapa 1 de 3). A seção 1 de referência (V1.2.1 §6 B-B / B-T / B-LT / B-LTA) define combinações fixas de atributos CMS; a seção 2 §5 define uma família paralela de "perfis estendidos" (E-BES / E-EPES / E-LTV) com maior flexibilidade opcional nos atributos CMS para usuários que precisam de mais recursos do que a versão básica (por exemplo, implantações empresariais com várias políticas, perfis CAdES personalizados dentro do envelope PAdES).
  • O parâmetro de perfil `AddPAdESSignatureField` agora aceita três valores adicionais, além dos quatro nomes básicos:
    • `'E-BES'` — assinatura básica e inequívoca, vinculada ao certificado de assinatura por meio do atributo ESS (equivalente a CAdES-BES dentro do envelope PAdES). Orçamento padrão de 16 KB para o conteúdo.
    • `'E-EPES'` — E-BES + atributo de identificador de política de assinatura explicitamente assinado. Orçamento padrão de 16 KB; o chamador normalmente passa 18-20 KB para acomodar os bytes do OID da política + qualificadores.
    • `'E-LTV'` — validação de longo prazo com cadeia de certificados flexível de atributo CMS + incorporação de revogação. Aumenta automaticamente para um mínimo de 20 KB (espelha B-LT).
  • O formato interno do gerador é idêntico para os perfis básicos e estendidos — todos os sete usam o SubFilter `ETSI.CAdES.detached`, o mesmo padrão de sentinela /ByteRange + /Contents e a mesma estrutura DSS + ESIC (v2.110 / v2.116). A distinção de nível reside inteiramente na composição de atributos assinados do CMS, que é produzida pela biblioteca criptográfica do chamador. A string do perfil varia apenas no diagnóstico de validação e no orçamento padrão de /Contents; o HotPDF não codifica CAdES-BES vs CAdES-EPES vs CAdES-T diretamente no dicionário PDF.
  • Atualizado o comentário de documentação do helper PAdES para esclarecer as responsabilidades do chamador, conforme especificado na Parte 2, versão 1.2.0, §4.2: seleção de hash SHA-256 (descontinuação do SHA-1), um único objeto SignerInfo por campo Sig, ausência de certificados de atributo RFC 5755 e a exigência de E-EPES de incluir o atributo assinado signature-policy-identifier. Os itens relacionados ao domínio do chamador permanecem fora do escopo do produtor, mas o contrato agora está explicitamente definido na interface da API.
  • Compilação limpa para Win32 e Win64; todas as versões base de v2.108 a v2.116 foram recompiladas sem alterações. O módulo `smoke_pades_signature` foi expandido com 3 novos campos (SigEBES / SigEEPES / SigELTV), testando cada novo valor de perfil através dos caminhos de redimensionamento automático, orçamento explícito e orçamento padrão. O verificador em Python foi aprimorado para percorrer todos os 7 campos e verifica a extensão Catalog ESIC (incorporado na versão v2.116).
  • Etapa 2 da série B/C/D: a versão v2.118 adiciona Valores Iniciais (PDF 1.7 §12.7.5.5 + ETSI EN 319 142-1 V1.2.1 §5.5 + Parte 2 V1.2.0 §4.2.6) para que os campos de assinatura PAdES possam declarar restrições de manipulador/SubFilter/método de resumo que o leitor deve respeitar durante a assinatura. Etapa 3: a versão v2.119 adiciona suporte para contêiner XAdES-in-PDF de acordo com a Parte 2 V1.2.0 §6 (XML assinado por XAdES incorporado como EmbeddedFile + associação Catalog /AF).

2026-05-20 Version 2.116.0

  • Atualização do PAdES de acordo com as últimas versões normativas da ETSI e a Decisão de Implementação eIDAS: ETSI EN 319 142-1 V1.2.1 (2024-01, publicado) + ETSI EN 319 142-2 V1.2.0 (2025-03, rascunho de perfis adicionais + família de perfis estendidos + XAdES-in-PDF) + ETSI TS 119 142-3 V1.1.1 (2016-12, PAdES-DTS Document Time-stamp) + EU 2015/1506 (reconhecimento do setor público). As versões base do HotPDF v2.109 - v2.111 (B-B / B-T / B-LT / B-LTA + carimbo de tempo independente) continuam a satisfazer o mesmo formato de dados; esta atualização corrige duas lacunas do lado do produtor que as novas versões das especificações revelaram.
  • A entrada do dicionário `/Type "DSS"` (EN 319 142-1 V1.2.1 §5.4.2.2). A entrada `/Type` é opcional, mas, quando presente, deve ser o nome `/DSS`. O HotPDF agora a emite prontamente, para que validadores rigorosos que inspecionam `/Type` antes de percorrer o restante do dicionário reconheçam a estrutura imediatamente.
  • ESIC extensions dictionary (TS 119 142-3 §5.1, recomendado). O novo método `EnsurePAdESESICExtensions` grava de forma idempotente o seguinte no Catálogo sempre que um auxiliar PAdES é invocado: `<< /Extensions << /ESIC << /BaseVersion /1.7 /ExtensionLevel 1 >> >> >>`. Os validadores (Adobe Acrobat pre-flight, EU DSS, callas pdfaPilot) utilizam esta entrada para identificar o documento como um contêiner PAdES que declara as extensões de nível 1 do PDF 1.7 + ESIC.
  • Correção de um bug crítico no fluxo de ida e volta de `EnsurePAdESDSS`. Antes da versão v2.116, a função auxiliar resolvia novamente o dicionário DSS em cada chamada através de `Catalog.GetIndexedItem(FindValue('DSS'))`, o que retornava o link indireto `THPDFLink` armazenado no catálogo, em vez do dicionário DSS real. A conversão para `THPDFDictionaryObject` alterava silenciosamente o tipo do ponteiro, fazendo com que cada chamada subsequente de `AddPAdESDSSCertificate` / `AddPAdESDSSOCSP` / `AddPAdESDSSCRL` / `AddPAdESDSSVRI` ignorasse silenciosamente a adição ao array (a referência do array resolvia para nulo, `FindValue` retornava -1, e a saída antecipada `if-Idx-less-than-zero` era acionada). A correção na v2.116 armazena a referência real do dicionário em um campo `FPAdESDSSDict`, para que as chamadas subsequentes acessem diretamente o cache. O teste `smoke_pades_dss` agora emite corretamente 2 certificados + 1 OCSP + 1 CRL + 1 entrada VRI (anteriormente, apenas o primeiro certificado era incluído em /DSS, com os arrays /OCSPs e /CRLs vazios).
  • Atualizações nos comentários do código para as funções auxiliares PAdES, abordando as responsabilidades do chamador, conforme especificado na Parte 2, versão 1.2.0, §4.2: remoção da fase SHA-1 (os chamadores devem usar SHA-256+ para CMS), apenas um objeto SignerInfo por assinatura PDF (Parte 2, §4.2.1 h / Parte 1, §4.1 a), os certificados de atributo RFC 5755 não devem ser usados (Parte 2, §4.2 g), e os documentos PAdES-DTS não devem conter dicionários VRI (TS 119 142-3, §6.3 h — DSS é suficiente). O formato interno do HotPDF já atende a todas as quatro restrições por design; o comentário informa aos chamadores o que suas bibliotecas de construção de CMS devem fazer.
  • Compilação limpa para Win32 e Win64; os testes de assinatura, DSS e carimbo de data para PAdES, juntamente com seus verificadores, passaram com sucesso. As extensões do verificador agora incluem: `smoke_pades_dss` agora verifica `/Type /DSS` e `Catalog /Extensions /ESIC /BaseVersion /1.7 /ExtensionLevel 1`; `smoke_pades_doctimestamp` verifica a mesma extensão ESIC e aceita retângulos de área zero e espelhados verticalmente (`[0 H 0 H]`, onde H é a altura da página). A documentação de auditoria e as notas técnicas foram atualizadas para referenciar EN 319 142-1 V1.2.1 / Parte 2 V1.2.0 / TS 119 142-3 / EU 2015/1506.

2026-05-20 Version 2.115.0

  • PDF/X (ISO 15930) – finalização da série de produtores (4/4): tipos de anotações e ações proibidos, conforme ISO 15930-1:2001 / ISO 15930-3:2002 / ISO 15930-7:2010 + ISO 32000-1 §12.5.6 / §12.6.4. Os fluxos de trabalho de impressão PDF/X consomem apenas o conteúdo visível e imprimível; anotações multimídia, arquivos incorporados e ações interativas não têm função na impressão, portanto, ferramentas de pré-impressão (Adobe Acrobat, Enfocus PitStop, callas pdfaPilot) rejeitam documentos que os contenham.
  • Tipos de anotações proibidos (rejeitados em qualquer perfil PDF/XCompliance ∈ {X-1a, X-3, X-4}):
    • FileAttachment — a impressão não processa arquivos incorporados.
    • Sound — multimídia não tem lugar em fluxos de trabalho de impressão.
    • Movie — mesma justificativa para multimídia.
    Cada ponto de entrada (AddFileAttachmentAnnotation, AddSoundAnnotation, AddMovieAnnotation) agora gera um erro com a seção da especificação e o valor PDF/XCompliance quando invocado em qualquer perfil PDF/X.
  • Ações proibidas (rejeitadas em qualquer cenário de conformidade PDF/X): Launch, JavaScript, SubmitForm, ImportData, Movie, Sound, ResetForm. Os fluxos de trabalho de pré-impressão não devem acionar nenhum programa externo; o PDF é consumido apenas pela impressora/RIP e nunca executado. `AddLaunchLink` agora gera um erro em qualquer perfil PDF/X (as outras ações que o HotPDF não expõe como APIs públicas são satisfeitas automaticamente).
  • A série PDF/X agora está funcionalmente completa: v2.112 (opcional + identidade XMP + Trapped /Name) + v2.113 (OutputIntent + ICC GTS_PDFX) + v2.114 (controle de transparência + aplicação de restrições na PageBox) + v2.115 (proibição de anotações/ações). Todos os três perfis padrão da indústria (X-1a:2001, X-3:2002, X-4:2010) estão cobertos. O usuário continua a criar conteúdo de pré-impressão no nível da página (definindo corretamente os valores CMYK, incorporando fontes através do subsetor TTF v2.84, garantindo que as dimensões do TrimBox correspondam ao design e utilizando o BleedBox quando necessário), mas todas as verificações de conformidade estrutural estão implementadas.
  • Compilação limpa para Win32 + Win64; as versões base v2.108 a v2.114 foram recompiladas, sem alterações. O módulo `smoke_pdfx_optin` foi expandido com 4 novos testes de rejeição (TestRejectFileAttachmentAnnot, TestRejectSoundAnnot, TestRejectMovieAnnot, TestRejectLaunchAction) — cada um gera o tipo proibido em um dos três perfis PDF/X e confirma uma rejeição correta. No total, o conjunto de testes agora cobre 11 cenários: 3 emissões positivas + 8 caminhos de rejeição.
  • Duas séries de versões múltiplas e paralelas foram finalizadas neste grupo: PAdES (ETSI EN 319 142, v2.109 - v2.111, 3 commits, com suporte para B-B / B-T / B-LT / B-LTA e carimbo de tempo independente) e PDF/X (ISO 15930, v2.112 - v2.115, 4 commits, com todos os mecanismos de conformidade estrutural do lado do produtor implementados para X-1a / X-3 / X-4).

2026-05-20 Version 2.114.0

  • PDF/X (ISO 15930) série de implementações, parte 3/4: controle de transparência + aplicação obrigatória da PageBox, conforme ISO 15930-1:2001 / ISO 15930-3:2002 / ISO 15930-7:2010 + ISO 32000-1 §14.11.2. Esta implementação abrange duas restrições independentes que se aplicam a cada página; a divisão do controle espelha o padrão de transparência e recursos de página do PDF/A-1 v2.103.
  • Transparência (seção 7.5): RegisterExtGState rejeita valores de alfa de preenchimento menores que 1 (/ca), valores de alfa de contorno menores que 1 (/CA) ou modos de mesclagem fora de {Normal, Compatível} quando PDFXCompliance é 'X-1a' ou 'X-3'. O PDF/X-1a (ISO 15930-1:2001) e o PDF/X-3 (ISO 15930-3:2002) exigem a versão base do PDF 1.3, que é anterior à transparência do PDF 1.4. O PDF/X-4 (ISO 15930-7:2010, versão base do PDF 1.6) permite explicitamente a transparência, portanto, essa verificação não é aplicada no modo X-4. A mensagem de diagnóstico explica a causa e sugere atualizar para X-4 se a transparência for necessária.
  • Aplicação de restrições para a área da página (§14.11.2): um novo método chamado `EnsurePDFXPageBoxes` percorre cada página e exige que pelo menos uma das áreas, `/TrimBox` ou `/ArtBox`, esteja definida. Apenas a área `MediaBox` não é suficiente, pois ela representa a tela de design, e não as dimensões finais da página que a gráfica precisa saber para realizar o corte. Se as áreas da página estiverem ausentes, um erro é gerado, indicando o índice da página (começando em 1), a seção da especificação e a chamada recomendada para `SetTrimBox`. O mecanismo `EndDoc PDFXCompliance` chama automaticamente `EnsurePDFXPageBoxes` após a verificação de `OutputIntent`.
  • Padrão de chamada típico: após definir PDFXCompliance + Trapped + AddPDFXOutputIntent, cada página do documento deve incluir `CurrentPage.SetTrimBox(Left, Bottom, Right, Top)` correspondendo às dimensões do produto final (por exemplo, 0 0 612 792 para US Letter, 0 0 595 842 para A4). Recomenda-se o uso de BleedBox, mas não é obrigatório.
  • Compilação limpa para Win32 e Win64; as versões base v2.108 a v2.113 foram recompiladas, sem alterações. O módulo `smoke_pdfx_optin` foi aprimorado com: chamada positiva de `SetTrimBox` em cada um dos 3 perfis, tratamento de rejeição para `TrimBox` ausente, tratamento de rejeição para transparência X-1a (o uso de `RegisterExtGState` com `ca=0.5` gera um erro), tratamento positivo para transparência permitida X-4 (a mesma chamada é bem-sucedida e o `ExtGState` é registrado). O verificador em Python percorre cada dicionário `/Type /Page` e verifica se pelo menos um de `/TrimBox` ou `/ArtBox` está presente em cada página.
  • A versão v2.115 do PDF/X finaliza a série, removendo tipos de ação proibidos (JavaScript / Launch / SubmitForm / ImportData / Movie / Sound), tipos de anotação proibidos (Movie / Sound / FileAttachment / Screen) e rejeitando AcroForm /XFA. Os fluxos de trabalho de impressão não devem incluir esses recursos; as ferramentas de verificação prévia para usuários finais os identificam como falhas críticas.

2026-05-19 Version 2.113.0

  • PDF/X (ISO 15930) série de implementações, fatia 2/4: Aplicação de OutputIntent + perfil ICC conforme 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. Cada perfil PDF/X exige pelo menos uma entrada do tipo /Type /OutputIntent /S /GTS_PDFX, que nomeia a condição de impressão de destino e fornece o fluxo de perfil ICC /DestOutputProfile — as gráficas usam isso para ajustar a cor do PDF à combinação de sua impressora/papel/tinta.
  • Novo utilitário `AddPDFXOutputIntent(OutputConditionIdentifier, Info, ICCProfileStream, NumComponents, AlternateCS)` espelha o wrapper PDF/A da versão v2.102, mas emite o subtipo GTS_PDFX em vez de GTS_PDFA1. Valida se `ICCProfileStream` não é nulo e se `OutputConditionIdentifier` não está vazio; chama `RegisterICCProfile` para incorporar o perfil (gerencia automaticamente o espaço de cores alternativo /Alternate para corresponder a `NumComponents`) e `AddOutputIntent` para construir o dicionário `OutputIntent`.
  • Imposição do final do documento: quando PDFXCompliance está definido, EnsurePDFXOutputIntent percorre o array OutputIntents e exige pelo menos uma entrada com /S /GTS_PDFX + /DestOutputProfile. Se a entrada estiver ausente, um erro é gerado com a sugestão do identificador registrado (FOGRA39 para impressão offset, CGATS TR 001 SWOP para o mercado norte-americano, Japan Color 2001 Coated para mercados asiáticos).
  • Fluxo de trabalho típico PDF/X: 1) `Doc.PDFXCompliance := 'X-4'`, 2) `Doc.Trapped := 'False'`, 3) carregue o perfil ICC CMYK (FOGRA39 / SWOP / etc.) em um objeto TStream, 4) `Doc.AddPDFXOutputIntent('FOGRA39 (ISO 12647-2:2004)', '', ICCStream, 4, 'DeviceCMYK')`, 5) crie o conteúdo, 6) `Doc.EndDoc` emite a OutputIntent vinculada do array /OutputIntents no catálogo; ferramentas de pré-impressão (Adobe Acrobat, Enfocus PitStop, callas pdfaPilot) validam a combinação de gerenciamento de cores.
  • Compilação limpa para Win32 + Win64; as versões base v2.108, v2.109, v2.110, v2.111 e v2.112 foram recompiladas, sem alterações. O componente `smoke_pdfx_optin` (originalmente v2.112) foi expandido para: registrar um perfil ICC falso e adicionar `AddPDFXOutputIntent` em cada uma das três emissões de perfil (X-1a → FOGRA39 CMYK, X-3 → SWOP CMYK, X-4 → sRGB RGB) e adicionar um caminho de rejeição que verifica se a ausência de `OutputIntent` gera um erro. O verificador em Python foi expandido para percorrer todos os dicionários e confirmar a entrada `/Type /OutputIntent /S /GTS_PDFX` com `/DestOutputProfile` sendo emitida.
  • As fatias restantes do PDF/X: a versão v2.114 adiciona a restrição de transparência (o X-1a e o X-3 rejeitam valores de alfa de preenchimento/traçado ExtGState menores que 1 e bitmaps não normais; o X-4 permite a transparência) e impõe a aplicação da PageBox (cada página precisa de TrimBox ou ArtBox, conforme §14.11.2); a versão v2.115 finaliza a série com a proibição de ações e portfólios / anotações / XFA (vídeos, sons, anexos de arquivo, telas, JavaScript, inicialização, envio de formulário, importação de dados e XFA são todos rejeitados, pois os fluxos de trabalho de impressão não devem usá-los).

2026-05-19 Version 2.112.0

  • Iniciada a série de produtos para pré-impressão PDF/X (ISO 15930). PDF/X é a família ISO para enviar arquivos PDF prontos para impressão para gráficas comerciais; os perfis X-1a (CMYK estrito + cores especiais), X-3 (gerenciamento de cores ICC) e X-4 (transparência PDF 1.6 + ICCN) são os três mais utilizados na indústria. A versão 2.112 é a parte 1/4: propriedade opcional + metadados de identificação. Uma auditoria completa e um roteiro de 4 versões foram arquivados em .superpowers/specs/2026-05-19-pdfx-compliance-audit.md.
  • Uma nova propriedade `PDFXCompliance: AnsiString` foi adicionada ao THotPDF e aceita `''` (desativado, padrão), `'X-1a'` (ISO 15930-1:2001), `'X-3'` (ISO 15930-3:2002) ou `'X-4'` (ISO 15930-7:2010). Ao definir um valor diferente de vazio, todas as exigências que o HotPDF pode atender estruturalmente para aquele perfil são automaticamente habilitadas.
  • Nova propriedade `Trapped: AnsiString` (obrigatória em PDFXCompliance) aceita os valores `'True'` / `'False'` / `'Unknown'`. A família de padrões PDF/X exige esta entrada em DocInfo para que a gráfica saiba se o PDF já foi processado para separação de cores ou se é necessário realizar esse processo na pré-impressão. É emitida como um objeto PDF /Name (e não como uma string), conforme especificado em ISO 32000-1 §14.11.6.1; por exemplo, `<< /Trapped /False >>`.
  • Identificação de metadados XMP: o pacote agora anuncia `xmlns:pdfx="http://ns.adobe.com/pdfx/1.3/"` com `` definido para a string exata especificada (`PDF/X-1:2001`, `PDF/X-3:2002` ou `PDF/X-4`) e (para X-1a + X-4) `` definido para o nome completo do perfil (`PDF/X-1a:2001` ou `PDF/X-4:2010`). O Adobe Acrobat, o Enfocus PitStop e o callas pdfaPilot reconhecem o documento como um candidato PDF/X.
  • Validação de EndDoc: rejeita valores de perfil desconhecidos, rejeita valores de "Trapped" vazios ou não reconhecidos, exige um título e atualiza automaticamente a versão do PDF para a versão mínima obrigatória especificada no perfil (X-1a/X-3 → PDF 1.3, X-4 → PDF 1.6). A criptografia e a conformidade PDF/X são incompatíveis; chamar EnableEncrypt (ou `ActivateProtection := True`) gera um erro com uma mensagem clara explicando que os fluxos de trabalho PDF/X devem inspecionar todos os objetos sem tratamento de senhas.
  • O chamador continua sendo responsável por definir a intenção de saída + perfil ICC + TrimBox/ArtBox + espaços de cores de pré-impressão válidos + incorporação correta de fontes (e evita transparência para X-1a/X-3) para garantir a conformidade total com o padrão PDF/X. As versões v2.113 a v2.115 corrigem essas lacunas: a v2.113 adiciona `AddPDFXOutputIntent` (intenção /GTS_PDFX obrigatória), a v2.114 adiciona um filtro de transparência + aplicação de restrições à PageBox, e a v2.115 finaliza a série com restrições para ações/anotações/XFA proibidas.
  • Compilação limpa para Win32 + Win64; as versões base v2.108 / v2.109 / v2.110 / v2.111 foram recompiladas sem alterações. O novo teste smoke_pdfx_optin gera três arquivos PDF (um para cada perfil) e verifica o namespace XMP + GTS_PDFXVersion + GTS_PDFXConformance, além de DocInfo /Trapped /Name, e também testa caminhos de rejeição para perfis inválidos, campos Trapped vazios, Trapped desconhecidos e conflitos de criptografia.
  • Notas da série PAdES: as versões v2.109 / v2.110 / v2.111 abrangem os casos de uso B-B / B-T / B-LT / B-LTA, além do uso independente de carimbos de data/hora. A versão v2.112, originalmente planejada (um PDF com apenas um carimbo de data/hora ETSI.RFC3161), é efetivamente implementada implicitamente — a função `AddDocumentTimestampSignature` da versão v2.111 funciona em um documento novo, sem uma assinatura interna — portanto, a série PAdES é considerada finalizada em 3 commits, e a versão v2.112 será realocada para PDF/X. Todos os perfis de linha de base ETSI EN 319 142-1 são suportados.

2026-05-19 Version 2.111.0

  • Série de produtos PAdES, fatia 3/4: Suporte para assinatura de carimbo de tempo de documento PAdES-B-LTA, conforme ISO 32000-1 §12.8.5 + ETSI EN 319 142-1 §5.7. O carimbo de tempo do documento é uma segunda assinatura aplicada APÓS a conclusão da assinatura de validação de longo prazo; ele cobre todo o arquivo de estado de longo prazo (assinatura original + DSS) e comprova que o material de longo prazo existiu em um momento autenticado. Este é o perfil de arquivamento necessário para a retenção regulamentada pela UE, além da vida útil do certificado CA original.
  • Novo utilitário `THPDFPage.AddDocumentTimestampSignature(FieldName, ContentsBytes)`. Diferentemente de uma assinatura PAdES normal, um carimbo de data e hora de documento possui:
    • SubFiltro `/ETSI.RFC3161` (um TimeStampToken RFC 3161, e não CAdES).
    • Retângulo de widget com área zero (um carimbo de data e hora não tem aparência visível — apenas metadados criptográficos).
    • Sem `/Reason`, `/Location`, `/ContactName` (esses campos estão nos atributos assinados do TST, e não no dicionário da assinatura).
    • Orçamento padrão de bytes para `/Contents` de 16 KB (o chamador pode passar um valor menor, até um mínimo de 1 KB; um TST RFC 3161 completo com cadeia de certificados geralmente tem de 4 a 8 KB).
  • O escopo do produtor termina no formato de arquivo: o helper cria o dicionário placeholder /Type /Sig com o SubFilter específico do timestamp e um marcador /ByteRange + /Contents para correção posterior via PreparePDFForSigning + InsertSignatureHex. O chamador obtém os bytes TST reais do RFC 3161 de uma Autoridade de Timestamp Confiável (TSA, por exemplo, DigiCert / GlobalSign / FreeTSA HTTP POST) e os injeta. O fluxo de trabalho típico de arquivamento PAdES-B-LTA é o seguinte: 1) emite a assinatura base PAdES-B-LT (v2.109), 2) preenche o Catalog /DSS com a cadeia de certificados + OCSP/CRL (v2.110), 3) salva como atualização incremental, 4) adiciona o campo de timestamp do documento sobre os bytes do estado LT (v2.111), 5) solicita o TST da TSA sobre a faixa de bytes, 6) injeta os bytes do TST.
  • Compilação limpa para Win32 + Win64; as versões base v2.108 / v2.109 / v2.110 foram recompiladas, sem alterações. O novo módulo "smoke_pades_doctimestamp" gera um campo "SigInner" do tipo PAdES-B-LT, além de um campo de carimbo de data/hora do documento ("DocTS"), usando um novo utilitário. O verificador Python garante que a assinatura interna tenha o filtro "/SubFilter /ETSI.CAdES.detached", que o widget de carimbo de data/hora tenha uma área de "/Rect" igual a zero, que o dicionário "/V" do carimbo de data/hora tenha o filtro "/SubFilter /ETSI.RFC3161" e não contenha os campos "/Reason", "/Location", "/ContactName", e que o conteúdo seja um espaço reservado de 16 KB (32768 caracteres hexadecimais).
  • Versão v2.112 (opcional) do componente PAdES adiciona arquivos PDF com carimbo de tempo ETSI.RFC3161 independentes (sem assinatura interna CAdES — apenas um contêiner de documento de carimbo de tempo).

2026-05-19 Version 2.110.0

  • A série de produtos PAdES, versão 2/4: suporte ao dicionário Document Security Store (DSS) conforme ISO 32000-2 §12.8.4.3 + ETSI EN 319 142-1 §5.6. O PAdES-B-LT (e B-LTA) exigem que informações relacionadas à validação – cadeia de certificados, respostas OCSP, CRLs – sejam incorporadas no próprio PDF, para que as assinaturas possam ser verificadas muito tempo depois do momento original da assinatura, sem a necessidade de consultar servidores PKI externos.
  • Novas funcionalidades em THotPDF:
    • `EnsurePAdESDSS` — cria de forma preguiçosa o dicionário indireto do catálogo /DSS com seus arrays /Certs, /OCSPs, /CRLs e um sub-dicionário /VRI vazio; chamadas subsequentes retornam o dicionário existente.
    • `AddPAdESDSSCertificate(CertDERBytes)` — adiciona um certificado X.509 codificado em DER como um fluxo indireto para /DSS /Certs; retorna o objeto de fluxo indireto para uso em referências VRI.
    • `AddPAdESDSSOCSP(OCSPDERBytes)` — o mesmo para a resposta básica OCSP para /DSS /OCSPs.
    • `AddPAdESDSSCRL(CRLDERBytes)` — o mesmo para a lista de revogação de certificados para /DSS /CRLs.
    • `AddPAdESDSSVRI(SigContentsHexSHA1, Certs, OCSPs, CRLs)` — cria uma entrada VRI específica para cada assinatura, usando o hash SHA-1 hexadecimal em letras maiúsculas do conteúdo da assinatura (a chave exigida pela especificação); cada entrada contém os arrays /Cert, /OCSP e /CRL, que fazem referência aos fluxos indiretos criados anteriormente.
  • O escopo do produtor termina no formato de arquivo. O chamador ainda calcula o SHA-1 do conteúdo assinado final e fornece os certificados DER codificados / respostas OCSP / CRLs de suas ferramentas PKI. Fluxo de trabalho típico: construa a assinatura base PAdES-B-T (v2.109), adicione certificados / OCSPs / CRLs ao DSS para verificação de longo prazo e, em seguida, anexe as entradas VRI que vinculam as informações de validação a assinaturas específicas.
  • Compilação limpa para Win32 e Win64; as versões base v2.108 e v2.109 foram recompiladas sem alterações. O novo teste "smoke_pades_dss" cria um campo de assinatura PAdES-B-LT, adiciona 2 certificados + 1 OCSP + 1 CRL ao DSS e adiciona uma entrada VRI com um resumo hexadecimal de teste. O verificador em Python percorre a estrutura do dicionário DSS: referência a "Catalog /DSS", "/Certs" (vazio), "/OCSPs" (vazio), array de contagens de "/CRLs", as chaves VRI correspondem, as referências de certificado/OCSP/CRL na entrada VRI correspondem aos arrays DSS de nível superior.
  • As fatias PAdES restantes: a versão 2.111 implementa a assinatura de carimbo de tempo de documento PAdES-B-LTA (segundo campo Sig com SubFilter ETSI.RFC3161 que cobre todo o arquivo LT); a versão 2.112 (opcional) adiciona arquivos PDF independentes que contêm apenas o carimbo de tempo.

2026-05-19 Version 2.109.0

  • Iniciado o trabalho de produção de assinaturas digitais PAdES (ETSI EN 319 142). A versão v2.109 adiciona uma camada de abstração de alto nível sobre a infraestrutura de assinatura existente ISO 32000-1 §12.8 (versão 2 do utilitário AddSignedSignatureField) que define o SubFilter obrigatório para PAdES e valida o perfil de conformidade. Uma auditoria completa e um roteiro de 4 versões foram arquivados em .superpowers/specs/2026-05-19-pades-compliance-audit.md.
  • Novo helper `THPDFPage.AddPAdESSignatureField(FieldName, Rect, Profile, Reason, Location, ContactName, ContentsBytes, Flags)`. O parâmetro Profile seleciona o nível base ETSI EN 319 142-1: 'B-B' (CAdES básico, sem timestamp), 'B-T' (com timestamp confiável RFC 3161, mínimo para uso legal na UE), 'B-LT' (com informações de validação DSS para verificação de longo prazo) ou 'B-LTA' (com assinatura de timestamp de documento para arquivamento). Todos os quatro usam o SubFilter 'ETSI.CAdES.detached'; o parâmetro profile varia o diagnóstico e o orçamento padrão de bytes /Contents. Outras strings de perfil geram um erro, conforme listado na enumeração ETSI.
  • Orçamento de conteúdo redimensionado automaticamente: PAdES-B-B + B-T padrão para 16 KB (o chamador pode fornecer um valor menor; nós impomos um limite mínimo de 64 bytes, herdado da versão v2.108). PAdES-B-LT redimensiona automaticamente para um mínimo de 20 KB (CAdES + cadeia de certificados + dados OCSP/CRL). PAdES-B-LTA redimensiona automaticamente para um mínimo de 24 KB (B-LT + carimbo de tempo do documento). Valores maiores fornecidos pelo chamador são aceitos; o utilitário apenas define o limite mínimo.
  • Escopo do produtor: o wrapper cria o dicionário placeholder /Type /Sig com /SubFilter /ETSI.CAdES.detached, /Reason, /Location, /ContactName e /M (data de assinatura), e o marcador /ByteRange + /Contents para correção posterior via PreparePDFForSigning + InsertSignatureHex. A obtenção dos bytes CMS / CAdES reais, a recuperação do timestamp RFC 3161, a coleta de OCSP/CRL e a construção do dicionário DSS permanecem de responsabilidade do chamador — isso requer uma biblioteca criptográfica externa (OpenSSL, Bouncy Castle, Windows CAPI, etc.) que está fora do escopo do produtor de PDF.
  • Compilação limpa para Win32 e Win64. O novo módulo "smoke_pades_signature" gera quatro campos de assinatura PAdES (B-B / B-T / B-LT / B-LTA) e verifica que valores de perfil inválidos geram erros. O verificador Python garante que o AcroForm possui /SigFlags 3, que cada widget possui /FT /Sig e uma referência indireta a um dicionário /Type /Sig com /SubFilter /ETSI.CAdES.detached, e que o comprimento hexadecimal do espaço reservado em /Contents corresponde ao tamanho esperado (ajustado automaticamente).
  • As próximas funcionalidades PAdES no roteiro incluem: a versão 2.110 adiciona o construtor de dicionário /DSS (Document Security Store) para informações de validação PAdES-B-LT (cadeia de certificados + OCSP/CRL); a versão 2.111 adiciona o campo de assinatura de carimbo de data/hora independente para arquivamento PAdES-B-LTA; a versão 2.112 (opcional) adiciona PDFs com apenas carimbo de data/hora ETSI.RFC3161.

2026-05-19 Version 2.108.0

2026-05-19 Version 2.107.0

  • PDF/A-2 + PDF/A-3: a implementação da seção 6.1.13 das normas ISO 19005-2 e ISO 19005-3 impõe limites. A seção 6.1.13 do PDF/A-1 é significativamente mais flexível (sem limite máximo para o comprimento de strings), portanto, a nova restrição só é aplicada quando a conformidade PDFA é PDF/A-2 ou posterior ('2*' / '3*').
  • Novo método público EnsurePDFAImplementationLimits valida os valores controlados pelo chamador no documento em relação aos limites rígidos da especificação: as strings Doc.Title / Author / Subject / Keywords / Lang devem ter ≤ 32767 bytes; a dimensão MediaBox de cada página deve estar no intervalo [3..14400] unidades. EndDoc invoca o validador automaticamente quando PDFACompliance é PDF/A-2/3; os chamadores também podem invocá-lo diretamente durante a construção para diagnósticos iniciais.
  • Os limites naturalmente definidos e documentados no relatório de auditoria são: intervalo de inteiros (-2³¹..2³¹-1), intervalo de números reais (±3.403×10³⁸, próximo de zero ≥1.175×10⁻³⁸), comprimento do nome ≤127 bytes, contagem de objetos indiretos ≤8388607, aninhamento q/Q ≤28, corantes DeviceN ≤32, CID ≤65535. Os caminhos de emissão do HotPDF nunca excedem esses limites porque estão vinculados a estruturas de dados controladas pelo produtor. O validador se concentra em strings fornecidas pelo chamador e nas bordas da página, porque esses são os únicos limites que um chamador real pode ultrapassar.
  • Formulários XFA (§6.4.2): O HotPDF não gera os elementos AcroForm /XFA ou Catalog /NeedsRendering. Ambos são naturalmente satisfeitos em PDF/A-1/2/3 – conforme documentado no relatório de auditoria, para que futuras extensões de produtores não os reintroduzam.
  • glifo .notdef (§6.2.11.8 em PDF/A-2): a especificação proíbe que os operadores de exibição de texto façam referência ao glifo .notdef. O tratamento de fontes do HotPDF evita isso quando os chamadores usam fontes TTF Unicode registradas (versão 2.74 a 2.86), pois o criador mapeia cada ponto de código para um glifo real ou recusa o registro. A responsabilidade pelo emissão de texto bruto é do chamador; isso está documentado no relatório de auditoria.
  • Espaço de nomes XMP (§6.6.2): a especificação proíbe o atributo de bytes/codificação no cabeçalho do pacote XMP. A função BuildXMPPacket emite um cabeçalho mínimo (id="W5M0MpCehiHzreSzNTczkc9d") sem nenhum desses atributos, o que satisfaz naturalmente todos os aspectos PDF/A.
  • Compilação limpa para Win32 e Win64. Novos testes "smoke" para "smoke_pdfa2_limits" com três caminhos: o teste PDF/A-2 dentro dos limites passa; o teste PDF/A-1 com um título de 32768 bytes também passa (sem a restrição de §6.1.13); o teste PDF/A-2 com um título de 32768 bytes é rejeitado com a mensagem de diagnóstico especificada. As linhas de base PDF/A-2/3 anteriores foram recompiladas sem alterações.
  • A fatia restante do processador PDF/A-2/3: a versão 2.108 implementa o PDF/A-3, Anexo E, Arquivos Associados (o recurso de contêiner híbrido específico do PDF/A-3: array /AF do catálogo de especificações de arquivos com a chave /AFRelationship + EmbeddedFile /Params /CheckSum + /ModDate).

2026-05-19 Version 2.106.0

  • PDF/A-2 + série de produtores PDF/A-3, versão 2/4: cobertura de PDF/A-2 §6.3.1 + §6.5.1 (e PDF/A-3 §6.3.1 + §6.5.1, que são idênticos). Os mecanismos de bloqueio de anotações e ações PDF/A-1 da versão 2.104 já estavam ativos para qualquer PDFACompliance não vazio, portanto, continuam a funcionar inalterados no PDF/A-2/3. A versão 2.106 confirma esse comportamento, atualiza as mensagens de diagnóstico para referenciar as seções unificadas da especificação em todas as partes do PDF/A e documenta os subtipos proibidos adicionados no PDF/A-2 que o HotPDF atende naturalmente (sem caminho de emissão público).
  • Matriz de ações proibidas: PDF/A-1 proíbe 6 ações (Iniciar / Som / Filme / RedefinirFormulário / ImportarDados / JavaScript). PDF/A-2 + PDF/A-3 expandem o conjunto de ações proibidas para 13, adicionando Ocultar / DefinirEstadoOCG / Renderização / Transição / IrParaVisualização3D + os subconjuntos obsoletos de definição de estado / operação nula. AddLaunchLink continua a gerar erros; HotPDF não possui uma entrada pública que gere as outras 12 ações, portanto, elas são automaticamente satisfeitas.
  • Matriz de tipos de anotações proibidos: PDF/A-1 proíbe FileAttachment / Som / Filme. PDF/A-2 / PDF/A-3 removem a proibição de FileAttachment (relaxada na v2.105), mas adicionam 3D / Tela à lista de itens proibidos. As funções AddSoundAnnotation + AddMovieAnnotation continuam a gerar erros em todas as partes do PDF/A; o HotPDF não possui um caminho para emitir 3D / Tela, portanto, essas restrições são naturalmente satisfeitas.
  • Atualização da mensagem de diagnóstico: os três "gates" da versão 2.104 (AddSoundAnnotation, AddMovieAnnotation, AddLaunchLink) agora referenciam todas as três seções relevantes da especificação em seu texto de erro (por exemplo, "PDF/A-1 §6.5.2 / PDF/A-2 §6.3.1 / PDF/A-3 §6.3.1"), para que os desenvolvedores vejam a proibição unificada. A mensagem AddLaunchLink também lista o conjunto estendido de ações proibidas para PDF/A-2/3.
  • Compilação limpa para Win32 e Win64. O novo teste "smoke_pdfa2_annot_action" verifica as três funcionalidades em todos os seis níveis PDF/A-2/3 (2B, 2U, 2A, 3B, 3U, 3A); cada chamada verifica a exceção esperada com um diagnóstico de acordo com as seções §6.3.1 / §6.5.1. As linhas de base PDF/A-1 anteriores (smoke_pdfa1_compliance / smoke_pdfa1_forbidden / smoke_pdfa1_annot_action) e o teste "smoke_pdfa2_compliance" da versão v2.105 foram recompilados sem alterações.
  • As fatias de produtor PDF/A-2/3 restantes: a versão v2.107 impõe os limites de implementação da ISO 19005-2 §6.1.13 (intervalos de bytes inteiros/reais/strings/nomes, aninhamento q/Q, corantes DeviceN, CID, limites de página) + §6.4.2 XFA + §6.2.11 Type 3 / .notdef estritos; a versão v2.108 implementa o PDF/A-3 Anexo E, que são arquivos associados (arquivos PDF híbridos com tipos de arquivos incorporados arbitrários).

2026-05-19 Version 2.105.0

  • Iniciamos uma série de quatro versões de conformidade com os padrões PDF/A-2 (ISO 19005-2:2011) e PDF/A-3 (ISO 19005-3:2012). A auditoria e o roteiro foram arquivados em .superpowers/specs/2026-05-19-pdfa2-pdfa3-compliance-audit.md. A versão v2.105 introduz a opção de ativação da camada de wrapper, extensões do namespace XMP pdfaid, aumento automático da versão base do PDF para 1.7 e relaxamento seletivo das restrições rígidas das versões v2.101-104 do PDF/A-1, que são explicitamente permitidas nas especificações PDF/A-2 e PDF/A-3.
  • A propriedade PDFACompliance agora aceita seis novos valores, além dos existentes '' / 'A' / 'B': '2A' / '2B' / '2U' (níveis A / B / U do PDF/A-2) e '3A' / '3B' / '3U' (níveis A / B / U do PDF/A-3). O nível U é a nova camada "apenas preservação do Unicode" introduzida pelo PDF/A-2 (texto visual + extraível em Unicode, sem a exigência de PDF marcado).
  • BuildXMPPacket foi expandido: o elemento `` agora reflete o número da parte analisado (1 / 2 / 3) e `` reflete a letra do nível analisado (A / B / U). Validadores como veraPDF identificam a parte PDF/A do documento com base neste par. De acordo com ISO 19005-2 §6.6.4 + ISO 19005-3 §6.6.4 Tabela 8.
  • Auto-incremento: A opção PDFACompliance '2*' / '3*' incrementa automaticamente a versão do documento para PDF 1.7, pois tanto o PDF/A-2 quanto o PDF/A-3 são baseados no ISO 32000-1 (PDF 1.7). O PDF/A-1 permanece vinculado ao PDF 1.4.
  • v2.103: A restrição de transparência foi relaxada. Agora, `RegisterExtGState` gera um erro apenas quando há transparência e o modo de combinação não é "Normal", mas somente quando `PDFACompliance` está definido como PDF/A-1 estrito ('A' ou 'B'). As versões PDF/A-2 e PDF/A-3 §6.4 permitem explicitamente a transparência (com requisitos separados, como a presença de `OutputIntent` e os modos de combinação nomeados completos do PDF 1.4), portanto, `PDFACompliance` definido como '2*' ou '3*' permite que a chamada seja executada.
  • v2.104: A restrição para anexar arquivos foi relaxada. A função `AddFileAttachmentAnnotation` agora gera um erro apenas em conformidade estrita com PDF/A-1. A conformidade PDF/A-2 §6.3.1 proíbe apenas os tipos de anotações 3D / Som / Tela / Filme; anexos de arquivos são permitidos e são a base do fluxo de trabalho híbrido de arquivos associados do Anexo E do PDF/A-3. As outras restrições para anotações/ações (anotações de som e vídeo; ação de lançamento) ainda se aplicam a todas as conformidades PDF/A, de acordo com as proibições compartilhadas em §6.3.1 + §6.5.1.
  • Novos métodos auxiliares THotPDF, PDFAPart, PDFAConformanceLevel, IsPDFA1Strict e IsPDFA2OrLater, tornam a lógica de ramificação de valores mais eficiente. Os mecanismos existentes de PDF/A, nas versões v2.101 a v2.104, agora utilizam esses métodos auxiliares para caminhos de código mais limpos e mensagens de erro mais claras, que sugerem a transição para PDF/A-2 ou PDF/A-3 quando apropriado.
  • Compilação limpa para Win32 e Win64; as linhas de base v2.101-104 (smoke_pdfa1_compliance / smoke_pdfa1_forbidden / smoke_pdfa1_annot_action) foram recompiladas sem alterações. O novo teste smoke smoke_pdfa2_compliance gera quatro arquivos PDF (níveis 2B / 2U / 2A / 3U), testa o relaxamento de transparência da versão v2.103, o relaxamento de anexos de arquivo da versão v2.104, além de dois caminhos de validação (nível '4Q' inválido é rejeitado; o filtro de transparência PDF/A-1 ainda funciona). O verificador Python garante que o XMP pdfaid:part e a conformidade correspondam a cada nível, e que o nível 2A tenha herança de PDF marcado.
  • As fatias de produtor PDF/A-2/3 restantes: a versão 2.106 amplia o conjunto de ações proibidas de 6 para 13 (adicionados Hide, SetOCGState, Rendition, Trans, GoTo3DView; estado definido obsoleto / sem efeito), além de ajustar as restrições de tipo de anotação (adicionados 3D e Screen, removido FileAttachment); a versão 2.107 impõe os limites de implementação da ISO 19005-2 §6.1.13 e restringe o uso de XFA; a versão 2.108 implementa os arquivos associados do PDF/A-3, Anexo E (PDFs híbridos em contêiner).

2026-05-19 Version 2.104.0

  • PDF/A-1: a série de correções para o criador foi finalizada (fatia 4/4): foram eliminados os tipos de anotação proibidos (§6.5.2, como FileAttachment, Sound e Movie) e o subtipo de ação de inicialização (§6.6.1). Com a versão v2.104, todas as 17 lacunas identificadas no lado do criador durante a auditoria PDF/A-1 de 2026-05-19 (.superpowers/specs/2026-05-19-pdfa1-compliance-audit.md) foram corrigidas: os quatro pontos principais (§5, §6.7.11 de identificação, §6.1.3 de proibição de criptografia, §6.2.2 de OutputIntent e §6.4 de transparência), além dos diversos bloqueios de recursos proibidos.
  • §6.5.2 tipos de anotações proibidos: AddFileAttachmentAnnotation, AddSoundAnnotation e AddMovieAnnotation agora geram um erro no modo PDFACompliance, com uma mensagem de diagnóstico clara indicando a seção da especificação. De acordo com a especificação, "os tipos FileAttachment, Sound e Movie não devem ser permitidos" para evitar dependências de conteúdo externo e multimídia em arquivos de arquivo.
  • §6.6.1 Ação de lançamento: `AddLaunchLink` agora gera uma exceção em `PDFACompliance` com uma mensagem de diagnóstico que identifica o alvo do lançamento. De acordo com a especificação, "As ações de Lançamento, Som, Filme, Redefinir Formulário, Importar Dados e JavaScript não devem ser permitidas." Os outros cinco subtipos de ação proibidos (Som/Filme/Redefinir Formulário/Importar Dados/JavaScript) não possuem um ponto de entrada público do HotPDF que os gere, portanto, são naturalmente atendidos sem mecanismos de controle explícitos.
  • PDFUACompliance e PDFACompliance, quando combinados, agora funcionam corretamente em todas as quatro versões do PDF/A. As duas opções se complementam: o nível A herda o PDFUACompliance, que é ativado automaticamente para PDFs com tags; ambas as opções aplicam suas próprias proteções específicas (Suspeitos/Abas/Idioma para PDF/UA; Criptografia/Transparência/Anotações/Ação para PDF/A) sem interferência.
  • Resumo do encerramento da auditoria: todos os requisitos de formato de arquivo §6 do lado do produtor para PDF/A-1 que o HotPDF pode atender estruturalmente foram resolvidos. As responsabilidades do chamador restantes (§6.1.5 equivalência Info-XMP, §6.2.3.3 correspondência de espaço de cores ↔ OutputIntent, §6.3 especificações de fonte, onde o trabalho PDF/UA já foi tratado na versão v2.74-v2.86) estão alinhadas com as responsabilidades correspondentes do chamador em PDF/UA-1.
  • Compilação limpa para Win32 e Win64; v2.103 recompila o arquivo smoke_pdfa1_forbidden de forma limpa. O novo teste smoke smoke_pdfa1_annot_action executa todos os quatro caminhos controlados (AddFileAttachmentAnnotation, AddSoundAnnotation, AddMovieAnnotation, AddLaunchLink) sob PDFACompliance e verifica que cada chamada gera um erro com um diagnóstico de §6.5.2 ou §6.6.1.
  • A superfície do produtor PDF/A-1 agora está totalmente fechada para auditoria. As futuras extensões PDF/A-2 (baseada em ISO 19005-2:2011 e PDF 1.7, que permite transparência e camadas) e PDF/A-3 (ISO 19005-3:2012, que permite arquivos incorporados para fluxos de trabalho híbridos) permanecem como possíveis candidatas futuras, dependendo da demanda do usuário.

2026-05-19 Version 2.103.0

  • PDF/A-1 producer series, versão 3/4: corrigido §6.4 Transparência (lacuna crítica #15) + §6.2.8 função de transferência /TR em ExtGState (lacuna #14). Duas lacunas do §6 relacionadas aos caminhos de produção existentes do HotPDF são naturalmente satisfeitas sem alterações no código: §6.1.10 filtro LZW (o HotPDF emite apenas FlateDecode em seu caminho de escrita) e §6.2.4 interpolação de imagem (/Interpolate) (o HotPDF nunca emite /Interpolate). Estes agora estão documentados como automáticos no relatório de auditoria.
  • §6.4 A transparência proíbe valores alfa diferentes de 1.0 e modos de combinação diferentes de Normal/Compatível. O `RegisterExtGState` agora é controlado pelo `PDFACompliance`: um valor alfa menor que 1 para preenchimento gera um erro (o PDF/A-1 requer `/ca = 1.0`); um valor alfa menor que 1 para o contorno gera um erro (`/CA = 1.0`); um modo de combinação diferente de `Normal` ou `Compatível` gera um erro. Todos os três diagnósticos indicam a seção da especificação e o valor problemático. O estado ExtGState padrão (sem chaves alfa, sem modo de combinação) e os valores permitidos explícitos (valores alfa de 1.0, modos de combinação Normal/Compatível) permanecem inalterados.
  • §6.2.8 O ExtGState proíbe a chave de função de transferência /TR (obsoleta; o PDF/A-1 permite apenas /TR2 com o valor /Default, e mesmo isso é melhor evitar). RegisterTransferFunctionState agora gera um erro no modo PDFACompliance, com um diagnóstico claro. Os usuários que precisam de funções de transferência para fluxos de trabalho PDF/X ainda podem usar a função auxiliar fora do modo PDFACompliance.
  • §6.1.10 LZW + §6.2.4 Interpolate: documentado como naturalmente atendido pelos caminhos de produção existentes do HotPDF (escritor apenas com FlateDecode, sem emissão de /Interpolate). Não são necessárias alterações no código; foi sinalizado nos comentários do relatório de auditoria para que futuros usuários não os reintroduzam.
  • Compilação limpa para Win32 e Win64; v2.102, recompilação limpa de smoke_pdfa1_compliance. O novo teste smoke smoke_pdfa1_forbidden executa todos os três caminhos controlados (ca<1, CA<1, BM=Multiply, registro /TR) e também verifica que os caminhos permitidos (ca=1.0, CA=1.0, BM=Normal/Compatible, sem alfa) ainda passam. Nenhum verificador — o próprio teste smoke verifica através de try/except que cada chamada controlada lança uma exceção.
  • Restante da parte do processador PDF/A-1: a versão v2.104 corrige os tipos de anotações proibidos (§6.5.2) (FileAttachment, Sound, Movie) + as regras de anotação /F /AP (§6.5.3) + os tipos de ação proibidos (§6.6.1) (Launch, Sound, Movie, ResetForm, ImportData, JavaScript) + os campos de formulário /A /AA + /NeedAppearances. Após a versão v2.104, a parte do processador PDF/A-1 estará totalmente fechada para auditoria.

2026-05-19 Version 2.102.0

  • PDF/A-1 (ISO 19005-1:2005) série de produtores, fatia 2/4: corrigido §6.2.2 OutputIntent + lacuna do perfil ICC. A nova função de alto nível `AddPDFAOutputIntent(OutputConditionIdentifier, Info, ICCProfileStream, NumComponents, AlternateCS)` simplifica o padrão de duas chamadas (v2.51 RegisterICCProfile + AddOutputIntent('GTS_PDFA1', ...)) em uma única chamada. O PDF/A-1 estrito exige uma entrada com `/Type /OutputIntent /S /GTS_PDFA1` e um fluxo ICC `/DestOutputProfile` válido; sem isso, os arquivos compatíveis não podem reproduzir as cores com precisão em diferentes plataformas.
  • O recurso PDFACompliance adiciona uma verificação `EnsurePDFAOutputIntent`: ele percorre a lista de OutputIntent registrados, procura pelo menos uma entrada com `/S /GTS_PDFA1` e `/DestOutputProfile`. Se essa entrada estiver ausente, é gerado um diagnóstico claro que indica a seção da especificação e direciona os usuários para a função `AddPDFAOutputIntent`. De acordo com §6.2.2 + Anexo A.
  • Fluxo de trabalho de arquivamento típico: forneça um perfil ICC sRGB IEC61966-2.1 para PDF/A otimizado para tela, FOGRA39 / GRACoL para impressão, ou o perfil CMYK registrado apropriado para pré-impressão. NumComponents deve ser 1 (cinza), 3 (RGB / Lab) ou 4 (CMYK) conforme a Tabela 66 da seção 8.6.5.5 do PDF 1.7; o componente auxiliar encaminha a validação para RegisterICCProfile.
  • O componente Helper valida: um OutputConditionIdentifier vazio gera um erro (a seção 6.2.2 exige o identificador); um ICCProfileStream nulo gera um erro (DestOutputProfile é obrigatório). Não retorna nenhum valor; o OutputIntent é registrado automaticamente em FOutputIntents e disponibilizado através do caminho de serialização existente do catálogo /OutputIntents.
  • Compilação limpa para Win32 e Win64; v2.101: `smoke_pdfa1_compliance` atualizado para chamar `AddPDFAOutputIntent` (com um arquivo ICC de 192 bytes simulado; os chamadores reais fornecem um arquivo ICC real). Um novo caso de validação verifica que a ausência de `OutputIntent` em `PDFACompliance` gera um diagnóstico de acordo com a seção §6.2.2. O verificador Python foi expandido para verificar o array `Catalog /OutputIntents`, percorrendo as entradas para encontrar `/S /GTS_PDFA1` com uma referência indireta a `/DestOutputProfile`.
  • Restante das partes do módulo de produção PDF/A-1: v2.103 corrige #15 Transparência (CRÍTICO) + #5 filtro LZW + #10 interpolação de imagem + #14 ExtGState /TR; v2.104 corrige #16 anotações FileAttachment/Sound/Movie + #17 regras de anotação /F /AP + #18 ações Launch/Sound/Movie/ResetForm/ImportData/JavaScript + #20 campos de formulário /A /AA + /NeedAppearances.

2026-05-19 Version 2.101.0

  • Iniciamos uma série de quatro versões de conformidade com o padrão PDF/A-1 (ISO 19005-1:2005) no lado do gerador, com a opção de ativação da camada de wrapper. O relatório completo de auditoria, com 17 itens, está arquivado em `.superpowers/specs/2026-05-19-pdfa1-compliance-audit.md`; a versão v2.101 implementa os componentes fundamentais (propriedade PDFACompliance, identificação XMP pdfaid, restrições para Title/Lang, proteção contra conflitos de criptografia). As versões v2.102 a v2.104 resolvem as lacunas restantes relacionadas ao gerenciamento de cores, transparência, fontes e anotações/ações.
  • Nova propriedade `PDFACompliance: AnsiString` que aceita '' (desativado, padrão), 'A' (Nível A: visual + PDF com tags + acessibilidade) ou 'B' (Nível B: preservação visual apenas). Valores inválidos geram um erro no final do documento. Em conformidade com a ISO 19005-1:2005 §5, níveis de conformidade.
  • Definir PDFACompliance como 'A' ativa automaticamente o PDFUACompliance (o nível A herda os requisitos de PDF marcado da seção 6.8, que correspondem aos requisitos de estrutura lógica da seção 7 do PDF/UA-1). Ambos os recursos podem ser combinados sem conflito; a camada v2.94 PDF/UA-1 de idioma/título/suspeitos é adicionada à camada de proteção v2.101 PDF/A.
  • Definir qualquer um desses níveis ativa automaticamente o recurso FEnableXMPMetadata, garantindo que o documento contenha o fluxo /Metadata XMP obrigatório. De acordo com a seção §6.7.2, os metadados do catálogo são obrigatórios.
  • BuildXMPPacket foi expandido: quando PDFACompliance não estiver vazio, o pacote XMP declara `xmlns:pdfaid="http://www.aiim.org/pdfa/ns/id/"` e inclui `1` e `A` (ou `B`). Os validadores veraPDF e similares dependem exatamente dessa combinação para classificar o documento como um candidato a PDF/A-1A ou 1B. De acordo com a Tabela 6 do §6.7.11, esquema de identificação PDF/A.
  • Título / Rigidez da linguagem: Quando o PDFACompliance está habilitado e Doc.Title='' ocorre, isso viola a seção (PDF/A-1 §6.7.3), que exige o campo dc:title no formato XMP, equivalente ao Info /Title. A rigidez da linguagem espelha o comportamento do PDFUACompliance na versão v2.94 (seção §6.8.4 para o Nível A), portanto, os autores devem escolher uma tag BCP-47 válida em vez de receber um fallback silencioso para 'en'.
  • Proteção contra conflitos de criptografia: de acordo com a seção 6.1.3, o trailer do arquivo não deve conter /Encrypt. A função EnableEncrypt (a função interna que é chamada quando as opções de senha do proprietário/usuário/proteção são definidas) agora gera um erro claro quando PDFACompliance não está vazio. A função EndDoc exibe o conflito pelo mesmo caminho, para que os chamadores vejam a falha antes da serialização.
  • A responsabilidade do lado do chamador ainda inclui: gerar um PDF/A-1 OutputIntent válido com perfil ICC (continuação da versão 2.102), evitar a transparência (versão 2.103), evitar tipos de anotações/ações proibidos (versão 2.104) e criar uma estrutura semântica real para o Nível A (coberto pelos utilitários de PDF marcado nas versões 2.96 a 2.99).
  • Compilação limpa para Win32 e Win64; a versão base v2.100 e o teste smoke_pdfua_link_contents foram recompilados com sucesso. O novo teste smoke smoke_pdfa1_compliance gera arquivos PDF nos níveis A e B, além de testar três caminhos de validação (nível Z inválido, título vazio, conflito entre criptografia e PDFACompliance). O verificador Python verifica os atributos xmlns:pdfaid, pdfaid:part=1 e a correspondência de pdfaid:conformance, dc:title, e o nível A adicionalmente possui /MarkInfo /Marked true, Catalog /Lang e /StructTreeRoot, além de xmlns:pdfuaid (herança automática).

2026-05-19 Version 2.100.0

  • Corrigido o problema de cobertura da anotação de hiperlink /Contents, conforme especificado em PDF/UA-1 §7.18.5, identificado na auditoria de 2026-05-19. A versão v2.95 adicionou a propriedade Description ao método AddURILink; a versão v2.100 estende o mesmo suporte para descrições alternativas aos três pontos de entrada de hiperlink restantes: AddGoToLink (salto dentro do documento), AddGoToRLink (salto entre arquivos) e AddLaunchLink (abertura de arquivo externo).
  • Cada função auxiliar recebe um parâmetro final opcional `const Description: AnsiString = ''`. Quando não está vazio, o dicionário de anotação contém uma entrada `/Contents (Description)`; sob `PDFUACompliance`, uma descrição vazia gera um erro com uma mensagem clara que identifica o link alvo problemático, para que a descrição alternativa ausente não passe despercebida. O valor padrão, vazio, preserva a compatibilidade com versões anteriores fora do modo PDFUACompliance.
  • De acordo com a especificação PDF/UA-1 §7.18.5, de forma rigorosa: "Os links devem conter uma descrição alternativa através da sua chave 'Contents', conforme descrito em ISO 32000-1:2008, 14.9.3." Esta especificação se aplica a todos os tipos de anotações de link, não apenas aos links URI - as assinaturas auxiliares agora tornam isso uniforme.
  • Fluxo de trabalho típico: `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');`
  • Compilação limpa para Win32 e Win64; a versão baseline smoke_pdfua_figure foi recompilada com sucesso. O novo teste smoke smoke_pdfua_link_contents cria um documento de 2 páginas com três anotações de link na página 0 (GoTo para a página 1, GoToR para 'companion.pdf', Launch para 'readme.txt') e também testa o caminho de exceção empty-Description para a conformidade PDFUA para todas as três anotações. O verificador Python garante que cada anotação de link possui /Subtype /Link, o tipo de ação correspondente /S /GoTo (ou /GoToR ou /Launch) e um valor /Contents que corresponde à Descrição fornecida.
  • Resumo da cobertura da superfície do produtor PDF/UA-1: com a versão v2.100, todos os quatro pontos de entrada de anotações de link agora atendem à seção §7.18.5. Combinado com o encerramento da auditoria da versão v2.94 (Suspects, Tabs, Lang), v2.95 (URI Contents, Bit 10, ID) e a série de ferramentas semânticas para PDF marcado das versões v2.96 a v2.99 (Heading, List, Table, Figure), a superfície do produtor PDF/UA-1 do HotPDF está agora totalmente encerrada por auditoria, tanto na camada de wrapper estrita em relação à especificação quanto na camada de API ergonômica.

2026-05-19 Version 2.99.0

  • Adicionado `BeginTaggedFigure(Parent, AltText, BBox): FigureElem` + `EndTaggedFigure` como a quarta e última parte da série de utilitários semânticos para PDF/UA-1 §7.3 (Gráficos). Esses elementos encapsulam operações de desenho fornecidas pelo chamador (objetos XImage, caminhos vetoriais, retângulos preenchidos) dentro de um elemento de estrutura Figure, com o atributo de layout /Alt obrigatório e o atributo /BBox opcional.
  • /Alt é obrigatório (não há fallback padrão vazio). De acordo com PDF/UA-1 §7.3, a especificação é rigorosa: "As tags de figura devem incluir uma representação alternativa ou texto de substituição que represente o conteúdo marcado com a tag de figura." Um texto Alt vazio gera um erro com um diagnóstico claro, indicando aos usuários a sobrecarga de 6 argumentos de `AddStructureElement` na versão v2.88, caso `/ActualText` (e não `/Alt`) seja o mecanismo de texto alternativo apropriado.
  • O BBox opcional é um array de 4 valores [llx, lly, urx, ury] que descreve a caixa delimitadora da figura no espaço de usuário padrão, e é anexado como /A << /O /Layout /BBox [...] >> de acordo com a ISO 32000-1 14.8.5.4.5, que define o proprietário do atributo Layout. Passe um array vazio para omitir completamente o atributo BBox. Um BBox com um número incorreto de elementos (1/2/3/5 ou mais) resultará em um erro, utilizando o layout de retângulo especificado como guia.
  • Fluxo de trabalho típico: `Fig := Doc.BeginTaggedFigure(Root, 'Logotipo da empresa: seta apontando para a direita', [72, 600, 200, 720]); ... desenhar o conteúdo da figura ... Doc.EndTaggedFigure;` A figura participa da mesma estrutura MCID / ParentTree que outros caminhos v2.90 BeginTaggedContent, mas com os atributos /Alt + /BBox anexados automaticamente.
  • Isso corrige a seção 7.3 sobre a responsabilidade do chamador, conforme especificado em PDF/UA-1, com base no relatório de auditoria. A série de ferramentas semânticas para PDF com marcação agora cobre todos os quatro tipos de estrutura principais: seção 7.4 (Título, v2.96), seção 7.6 (Lista, v2.97), seção 7.5 (Tabela, v2.98) e seção 7.3 (Figura, v2.99). Juntas, essas correções da camada de wrapper nas versões v2.94 e v2.95 tornam a funcionalidade de geração de PDF/UA-1 do HotPDF totalmente compatível com a especificação e, ao mesmo tempo, fácil de usar na API.
  • Compilação limpa para Win32 e Win64; a compilação básica de teste smoke_pdfua_table foi refeita com sucesso. O novo teste smoke smoke_pdfua_figure emite dois elementos de estrutura Figure (um com /Alt + /BBox, um com /Alt apenas) e também testa os caminhos de exceção para texto Alt vazio e BBox malformado. O verificador Python garante que ambos os tipos de Figure /S são válidos, que o conteúdo do texto /Alt corresponde e que os valores do array BBox são [72, 600, 200, 720].

2026-05-19 Version 2.98.0

  • Adicionados quatro utilitários para tabelas marcadas para PDF/UA-1 §7.5 (Tabelas), como a terceira parte da série de utilitários semânticos para PDF marcado. `BeginTaggedTable(Parent): TableElem` cria o contêiner da estrutura da tabela; `AddTaggedTableRow(Table): TRElem` adiciona uma linha TR; `EmitTaggedTableHeader(TR, X, Y, Text, Scope): THElem` emite uma célula TH com o atributo obrigatório /Scope; `EmitTaggedTableCell(TR, X, Y, Text): TDElem` emite uma célula de dados TD. Todos os cinco tipos de tags (Table, TR, TH, TD e o objeto de atributo) estão em conformidade com a especificação.
  • O atributo "/Scope" (ISO 32000-1 14.8.5.7 Tabela 350) é obrigatório no elemento auxiliar (sem valor padrão), com valores válidos `Row`, `Col` ou `Both`. Strings de "Scope" inválidas geram um erro, seguindo as diretrizes da especificação. PDF/UA-1 §7.5 é estrito: "Elementos de estrutura do tipo TH devem ter um atributo Scope. Se a estrutura da tabela não puder ser determinada por meio de cabeçalhos e IDs, então os elementos de estrutura do tipo TH devem ter um atributo Scope." Forçar o atributo Scope na assinatura do elemento auxiliar evita a falha de conformidade devido à ausência do atributo Scope.
  • A serialização do escopo segue o padrão de objeto de atributo: `/A << /O /Table /Scope / >>` (conforme ISO 32000-1 14.7.5.3 Class Map), para que os leitores interpretem como um atributo do namespace Table. O mesmo padrão é usado para o atributo List da versão 2.97: `/A << /O /List /ListNumbering ... >>`.
  • As tabelas e os elementos `TR` são apenas contêineres de estrutura (sem conteúdo marcado na página), mas os elementos `TH` e `TD` contêm texto visível, portanto, ambos passam pelo processo de `BeginTaggedContent + TextOut + EndTaggedContent`. Cada célula `TH` e `TD` recebe seu próprio MCID, operador `BDC` no fluxo de conteúdo da página e uma entrada `ParentTree`. Uma função auxiliar retorna o elemento `StructElem` da célula para que os chamadores possam adicionar atributos adicionais (por exemplo, a lista `/Headers` para tabelas complexas, `/RowSpan`, `/ColSpan`).
  • Fluxo de trabalho típico: `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')); ...` Substitui a estrutura de várias etapas da versão v2.90, além da sequência BDC/EMC para cada célula.
  • Isso corrige a seção 7.5 do PDF/UA-1 relacionada à responsabilidade do chamador, conforme indicado no relatório de auditoria. A série de ferramentas semânticas para PDF com tags agora cobre as seções 7.4 (Título, v2.96), 7.6 (Lista, v2.97) e 7.5 (Tabela, v2.98). A próxima etapa (v2.99+): criar uma ferramenta para a seção 7.3, que inclui a caixa delimitadora (/BBox), o texto alternativo (/Alt) e um bloco de desenho fornecido pelo chamador.
  • Compilação limpa para Win32 e Win64; a versão base v2.97 e o teste smoke_pdfua_list foram recompilados com sucesso. O novo teste smoke smoke_pdfua_table cria uma tabela de 3 linhas (1 cabeçalho + 2 dados) com 3 células TH (Scope=Col) + 6 células TD e testa a exceção de Scope inválido. O verificador Python garante a estrutura completa da tabela > TR > TH/TD, com /Scope /Col em cada célula TH.

2026-05-19 Version 2.97.0

  • Adicionadas duas funções auxiliares PDF/UA-1 §7.6 para listas, como a segunda parte da série de auxiliares semânticos para PDFs marcados: `BeginTaggedList(Parent, NumberingStyle): ListElem` cria o elemento de estrutura L com um objeto de atributo `/A` `<< /O /List /ListNumbering /