HotPDF Примечания к выпуску

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

  • Демо Delphi PreflightReport обновлено с console sample до интерактивного инструмента VCL GUI для single-file preflight workflows.
  • GUI теперь поддерживает стандартные отчеты text, JSON и HTML, необязательные пароли, profile INI files, встроенные presets, single-file PDF/VT validation, embedded-report PDF output, report preview, status logging, automatic output naming и быстрый доступ к созданным файлам.
  • Удалено прежнее поведение запуска, при котором sample PDF и report автоматически создавались, если command-line arguments не были переданы.

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 теперь повторно использует ресурс шрифта Type 0, созданный RegisterUnicodeTTF, для вывода Unicode из дополнительных плоскостей, поэтому текст страницы и потоки внешнего вида AcroForm используют один и тот же внутренний путь кодирования CID.
  • Общий этап финализации теперь синхронизирует вывод SMP на уровне страницы через FUnicodeUsedCps, /CIDToGIDMap, запись /W descendant font и /ToUnicode, избегая прежней локальной для страницы карты SMP.

2026-05-24 Version 2.121.2

  • THPDFPage.UnicodeTextOut теперь направляет символы Unicode из дополнительных плоскостей через зарегистрированную таблицу соответствия глифов формата 12 в шрифте страницы, когда RegisterUnicodeTTF загрузила активный шрифт. Эмодзи и другие скалярные значения U+10000 и выше отображаются как один глиф CID в потоке текста страницы, а не как два глифа-полу-суррогата.
  • Записи CMap для шрифта страницы `/ToUnicode` преобразуют идентификаторы глифов SMP обратно в исходную пару суррогатов UTF-16BE, сохраняя извлечение текста и доступность, при этом сохраняя существующий путь шрифта страницы `/CIDToGIDMap /Identity`.

2026-05-24 Version 2.121.1

  • Потоки внешнего вида AcroForm, созданные через RegisterUnicodeTTF, теперь отображают символы Unicode из дополнительных плоскостей, такие как emoji, через один внутренний CID вместо записи пары суррогатов UTF-16 как двух CID Identity-H. Сгенерированная /CIDToGIDMap указывает этот CID на реальный glyph, а /ToUnicode сопоставляет его обратно с исходной парой суррогатов UTF-16BE для извлечения текста.
  • Этап финализации Unicode-шрифта обновляет /CIDToGIDMap, /W и /ToUnicode после того, как все потоки внешнего вида зарегистрировали поздние внутренние CID-сопоставления, чтобы TrueType subsetting и сгенерированные внешние виды форм использовали окончательный набор использованных CID.

2026-05-23 Version 2.121.0

  • PDF 1.7 §12.6.4.13–15: действия мультимедиа (воспроизведение / звук / видео) получают три новых вспомогательных метода для кнопок на объекте `THPDFPage`: `AddPushButtonWithRenditionAction` для §12.6.4.13 (привязывает аннотацию Screen к данным MediaRendition + MediaClipData, описывающим аудио/видео фрагмент, и операции /OP 0..4); `AddPushButtonWithSoundAction` для §12.6.4.14 с двумя перегрузками (путь к файлу или необработанные данные `TBytes`), структурой `THPDFSoundParams`, предоставляемой вызывающей стороной (частота дискретизации / каналы / биты на отсчет / кодировка), а также необязательными параметрами /Volume, /Repeat и /Synchronous; `AddPushButtonWithMovieAction` для §12.6.4.15 (ссылается на аннотацию Movie через /Annotation и выбирает операции воспроизведения / остановки / паузы / возобновления).
  • AddScreenAnnotation и AddMovieAnnotation теперь возвращают созданный словарь аннотации, чтобы вызывающие функции могли использовать его в соответствующих вспомогательных функциях. Изменение сигнатуры с `procedure` на `function` совместимо с ABI Delphi; существующие вызывающие функции, которые вызывают эти процедуры и игнорируют результат, по-прежнему компилируются и создают PDF-файлы с идентичными байтами.
  • Стандартная глубина реализации: каждый вспомогательный компонент генерирует обязательные записи, указанные в спецификации, а также часто необходимые необязательные поля (Sound /Volume /Repeat /Synchronous; Rendition /JS). Необязательные параметры воспроизведения мультимедиа, параметры отображения на экране, селектор, а также параметры звука /Mix намеренно опущены — настройки по умолчанию в ридере охватывают 95% случаев, и вспомогательные компоненты остаются минимальными.
  • PDF/A (все уровни) и PDF/X (все профили) отклоняют все три мультимедийные операции при входе, используя диагностические сообщения, ссылающиеся на стандарты ISO (ISO 19005-1 §6.6.1 / ISO 19005-2 §6.5.1 / ISO 19005-3 §6.5.1 / ISO 15930). Существующие механизмы управления аннотациями, такие как `AddScreenAnnotation`, `AddSoundAnnotation` и `AddMovieAnnotation`, остаются в силе.
  • Действие Rendition связывает файл спецификации MediaClipData с /P /TF (TEMPACCESS) MediaPermissions в соответствии с §13.2.6.1, Таблица 280 — это минимальный уровень разрешений, который позволяет пользователю передать данные аудио/видео кодекам платформы.
  • По умолчанию, потоки звуковых действий устанавливают необязательные поля в значения, определенные в спецификации (Volume=1.0, Repeat=false, Synchronous=false), и передают их только в том случае, если вызывающая сторона передает значения, отличные от значений по умолчанию, что позволяет сохранить словарь действий максимально компактным для наиболее распространенных случаев.
  • 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.
  • Проверено с использованием новых версий Win32 и Win64. Тесты `smoke_multimedia_actions` (обеспечивают полное покрытие всех четырех вариантов действий, а также цепочку аннотаций Screen/Movie) и `smoke_multimedia_actions_pdfa_pdfx` (8 проверок, охватывающих 3 действия × PDF/A + PDF/X) прошли успешно. Регрессионный тест `smoke_button_actions` также проходит после рефакторинга процедур/функций `AddScreenAnnotation` и `AddMovieAnnotation`.

2026-05-23 Version 2.120.15

  • Исправлено: Функция EndDoc сериализовала граф объектов PDF до того, как были выполнены два этапа постобработки (инструмент для создания подмножеств TrueType из версии v2.84.0 и инструмент для автоматической вставки тегов /S в соответствии с PDF/UA-1 §7.18.3 из версии v2.94.0). В результате, ни одно из этих изменений не было применено к выходному файлу. Документы, использующие RegisterUnicodeTTF + AddTextField, включали в себя полный файл шрифта (около 1 МБ для латиницы и около 14 МБ для CJK) вместо подмножества (около 150 КБ / около 500 КБ). В поле /BaseFont отсутвал шестибуквенный префикс подмножества AAAAAA, в потоке /CIDSet в описателе шрифта отсутствовал необходимый элемент для соответствия стандарту PDF/A (veraPDF выявил несоответствие стандартам ISO 19005-1 §6.3.5 / -2 -3 §6.2.11), а PDF-документы, соответствующие стандарту PDF/UA-1, которые не содержали ключевое слово §7.18.3 /Tabs /S на аннотированных страницах, вызывали срабатывание правила 21-001 в программе Matterhorn и ошибки PAC 3 "Tabs".
  • Оба модификатора теперь выполняются ПЕРЕД SaveToStream / SaveToFile. Они перебирают список IndirectObjects и записывают PDF. Вывод идентичен v2.120.14 для документов, которые либо не регистрируют Unicode TTF, либо не включают PDFUACompliance; в этих случаях оба модификатора уже были неактивными, поэтому изменение порядка влияет только на документы, для которых вывод v2.120.14 был испорчен незаметно.
  • Проверено с помощью Win32 smoke_unicode_ttf_subset (подмножество, составляющее 33,6% от размера файла Arial на диске — сохранено 676 КБ — /BaseFont префикс UYENHH+ArialMT, согласованный для Type 0 / CIDFontType2 / FontDescriptor.FontName) и Win32 smoke_pdfua_annot_structparents (/Tabs /S указан на странице с аннотациями, все пять утверждений §7.18.3 + проверка структуры аннотаций выполнены успешно).

2026-05-23 Version 2.120.14

  • PDF/UA-1 строгий контроль структуры и ролей (ISO 14289-1 §7.7 + ISO 32000-1 §14.7.3): при включенной опции PDFUACompliance, функция AddStructureElement теперь отклоняет любые значения /S, которые не являются одним из 41 стандартного типа структуры, определенных в таблице 333 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), а также любые пользовательские роли, которые вызывающая сторона предварительно зарегистрировала с помощью AddStructRoleMap. В диагностическом сообщении об ошибке содержится строка недопустимой роли, указание на PDF/UA-1 §7.7 / таблицу 333 и предложение использовать AddStructRoleMap для исправления. Пустые значения роли также отклоняются с отдельным сообщением. Без этой проверки не соответствующие роли будут незаметно попадать в дерево структуры и вызывать ошибки "неизвестный тип структуры" в downstream-инструментах veraPDF / PAC.
  • Новый механизм срабатывает только в том случае, если PDFUACompliance имеет значение True; вызовы, не использующие UA, сохраняют прежнее поведение, определяемое байтом, начиная с версии v2.120.14. Все четыре перегрузки функции AddStructureElement (базовая версия с 4 аргументами типа AnsiString, перегрузка с 6 аргументами для /Alt и /ActualText, начиная с версии v2.88.0, перегрузка с 7 аргументами для /ID, начиная с версии v2.95.0, и перегрузка с перечислением THPDFStandardStructureType, начиная с версии v2.119.41) сходятся к одному и тому же пути, поэтому достаточно одного условия. Перегрузка с перечислением всегда передает имя из таблицы 333 и, следовательно, всегда проходит проверку; пользователи предпочитают ее, чтобы избежать опечаток или проблем с учетом регистра (например, 'Para' против 'P', 'Lbody' против 'LBody') во время компиляции.
  • v2.119.41 уже включала перечисление THPDFStandardStructureType (41 имя спецификации, сгруппированные по 5 категориям ролей PDF: §14.8.4.1 Группировка / §14.8.4.2 Элемент верхнего уровня / §14.8.4.3 Элемент встроенного уровня / §14.8.4.4 Ruby+Warichu / §14.8.4.5 Иллюстрация), функцию StandardStructureTypeToName(T) для сопоставления перечислений с именами и функцию IsStandardStructureType(Name) для проверки вызывающей стороной; v2.120.14 интегрировала эти возможности в точку входа AddStructureElement, чтобы строгая проверка была автоматической. Новый приватный вспомогательный метод _IsCustomRoleInRoleMap проходит динамический массив FStructRoleMap с помощью безопасного сравнения байтов, правильно сопоставляя имена ролей, отличных от ASCII, на хостах с CP_ACP=65001.

2026-05-23 Version 2.120.13

  • Исправлено: исходный код HotPDF v2.120.12 не компилировался в RAD Studio, поскольку две перегруженные функции EnableShapingFeatureForSubset оказались в опубликованной секции THotPDF, что вызывало ошибку E2266 (только один из набора перегруженных методов может быть опубликован). В версии v2.120.13 эти две перегрузки заключены в локализованную пару публичных секций, чтобы тот же публичный API компилировался без ошибок в dcc32 / dcc64; окружающие свойства и вспомогательные функции остаются опубликованными без изменений. Изменения не влияют на поведение во время выполнения.

2026-05-23 Version 2.120.12

  • EnableShapingFeatureForSubset (завершение этапа 8f): THotPDF.EnableShapingFeatureForSubset (FeatureTag) / the Перечисление всех таблиц подстановки GSUB, связанных с запрошенной функцией, в перегрузке THPDFShapingFeature. Установка состояния выбора GSUBScript / языка GSUBLanguage, перечисление всех потенциальных идентификаторов глифов для подстановки для LookupType 1 (Single — формат 1, изменение по сравнению с глифами Coverage + массив substituteGlyphIDs формата 2), LookupType 2 (Multiple — Sequence.substituteGlyphIDs[]), LookupType 3 (Alternate — AlternateSet.alternateGlyphIDs[]), LookupType 4 (Ligature — Ligature.ligatureGlyph), LookupType 5 / 6 (Contextual / Chained Contextual — рекурсивный переход в вложенные таблицы SequenceLookupRecord с ограничением глубины 8), LookupType 7 (Extension — автоматическое преобразование в фактический тип таблицы) и LookupType 8 (Reverse Chained — substituteGlyphIDs[]), и объединение идентификаторов глифов с помощью операции OR в FUnicodeExtraUsedGlyphs, чтобы подсистема создания подмножеств v2.84.0 включала все глифы, которые может создать функция, в подмножество встроенного шрифта. Этап 8f дополняет v2.119.50, позволяя пользователям, чьи конвейеры создания включают функцию глобально, использовать ее в пакетном режиме для каждого глифа.
  • Перечисление (enum) перенаправляет каждое значение THPDFShapingFeature в соответствующий набор тегов OpenType из 4 байт: 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. Перегрузка строкового тега принимает любой тег OpenType из 4 байт для точной настройки, выходящей за рамки предустановленных вариантов перечисления. Предупреждение о раздутии подмножества: включение широких функций (например, aalt Access All Alternates, некоторые шрифты включают каждый глиф в скрипте) может привести к тому, что большая часть набора глифов шрифта будет включена в подмножество, что сводит на нет работу по уменьшению размера, выполненную в версии v2.84.0; вызывающие функции должны предпочитать Phase 9 MarkUnicodeGlyphUsed, когда они знают точные GID, которые будут выданы. По умолчанию отключено, требуется явное включение. Закрывает последнюю оставшуюся подфазу дорожной карты двигателя GSUB, фаза 8.
  • Защитный контракт соответствует версии v2.119.50: шрифт не зарегистрирован, отсутствует таблица GSUB, используется тег, отличный от 4-байтного, соответствующая функция отсутствует в пути (скрипта, языка), цепочка поиска пуста — каждое условие "нет необходимости выполнять действие" приводит к молчаливому игнорированию (без исключений). Повторные вызовы являются идемпотентными (растровое изображение объединяется с помощью операции OR). Рекурсия вложенных подтаблиц формата 1/2 будет реализована в будущей версии; формат 3 является доминирующим для реальных шрифтов и реализован. Клиенты, которым требуется точная поддержка формата 1/2, могут использовать функцию per-glyph 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)` сохраняет одну запись (последовательность "заменитель → исходный"). Типичные сценарии использования: после множественной замены (1 GID → N GIDs), когда генерируется последовательность замен, регистрируется обратное соответствие, чтобы при копировании/вставке получатель мог вернуться к исходному коду; после замены лигатурами (N GIDs → 1 лигатура GID), генерируется лигатура, и регистрируется код лигатуры, который указывает на исходную последовательность из N элементов (например, произвольная контекстная лигатура CALT, которая преобразуется обратно в ее составные коды). `ClearToUnicodeReverseMappings` удаляет все зарегистрированные соответствия; `ToUnicodeReverseMappingCount` сообщает, сколько соответствий ожидают обработки.
  • EndDoc emit добавляет записи, зарегистрированные вызывающим, в виде дополнительных блоков bfchar после встроенного блока из 35 записей, автоматически разделяемых на подблоки по 100 записей в соответствии со спецификацией Adobe CMap и CIDFont Files (Technical Note #5014) §1.4.2, с ограничением оператора bfchar. Кодовые точки BMP генерируются как 4 шестнадцатеричных символа; кодовые точки SMP генерируются как пара суррогатов UTF-16BE (8 шестнадцатеричных символов) в соответствии со спецификацией Adobe CMap. Порядок регистрации сохраняется, поэтому семантика "последнего записанного имеет приоритет" для bfchar в PDF-ридерах обеспечивает вызывающим детерминированное поведение при переопределении встроенных 35 записей (если вызывающий регистрирует собственное сопоставление для <FB01> "fi", оно переопределяет значение по умолчанию v2.119.65 в ридере). Вызывающие, которые никогда не вызывают RegisterToUnicodeReverseMapping, сохраняют ToUnicode CMap идентичным базовой версии v2.120.10. SetFormUnicodeFontDict ('', nil) очищает реестр вызывающего, чтобы следующая регистрация шрифта Unicode началась с чистого листа.

2026-05-23 Version 2.120.10

  • Myanmar text shaper (версия 8f.10): регистрирует Myanmar (OpenType тег mymr) как десятый и последний индийский шрифт в HotPDF, охватывающий как основной блок Myanmar (U+1000-U+109F: Burmese, Mon, Sgaw Karen, Western Pwo, Shan, Rumai Palaung, Pa'o), так и расширенный блок Extended-A (U+AA60-U+AA7F). Новая функция ApplyMyanmarReorder выполняет предварительную обработку для изменения порядка символов, а GetMyanmarCategory осуществляет поиск символов по коду, и оба могут быть повторно использованы через диспетчер ApplyIndicReorder.
  • Наиболее сложная структура слогов в пакете: Kinzi 3-CP. Префикс (U+1004 + U+103A + U+1039) в начале слога обнаруживается, временно сохраняется и выводится в самом начале выходных данных в соответствии с R8; гласный звук E (U+1031) перед корневым слогом перемещается в начало слога в соответствии с R10; четыре медиальные согласные Y / R / W / H (U+103B-U+103E) собираются и выводятся в фиксированном порядке Y → R → W → H в соответствии с R9, независимо от порядка в исходном тексте.
  • ASAT (U+103A) и VIRAMA (U+1039) рассматриваются как вирамы для обработки кластеров согласных. DOT BELOW (U+1037) отображается под базовой строкой; другие знаки ударения отображаются над ней. ANUSVARA (Bindu) отображается над базовой строкой; VISARGA отображается после. Repha не используется.
  • Две записи в реестре `IndicScripts` (основной блок и расширение A) используют одни и те же функции упорядочивания для бирманского языка, поэтому согласные символы расширения A и диакритические знаки тона языка Па'о Карен отображаются прозрачно через диспетчер.
  • **Завершено 11 этапов обработки текста на индийских языках, отличных от деванагари, в пакетном режиме** (этапы 8f.0-8f.10): инфраструктура + 10 зарегистрированных индийских языков, включая деванагари, бенгали, гуджарати, тамильский, телугу, каннада, малаялам, сингальский (семейство Brahmic SIA), кхмерский и бирманский (юго-восточная Азия).
  • В соответствии с Unicode 16.0 §16.3 (Мьянма) и спецификацией форматирования OpenType для мьянманского языка.

2026-05-23 Version 2.120.9

  • Khmer text shaper (фаза 8f.9): регистрирует кхмерский (OpenType тег khmr, блок Unicode U+1780-U+17FF) как девятый индийский шрифт в HotPDF и первый шрифт Юго-Восточной Азии. Новый ApplyKhmerReorder выполняет предварительную обработку для изменения порядка символов, а GetKhmerCategory выполняет поиск символов по коду, и может быть повторно использован через диспетчер ApplyIndicReorder.
  • Независимая структура слогов (в отличие от брахмической схемы R1-R5, используемой в версиях 8f.1-8f.8): гласные, предшествующие корневому слогу (E / AE / AI / OE / OO / AU), перемещаются в начало слога; символы, изменяющие регистр (MUUSIKATOAN, TRIISAP), и другие символы, расположенные выше базовой строки, направляются в буфер верхнего уровня; символ Bindu (NIKAHIT) отображается над базовой строкой; символ Visarga (REAHMUK, YUUKALEAPINTU) отображается после базовой строки.
  • Обработка нижних индексов COENG: каждый символ COENG (U+17D2) + пара согласных образует кластер согласных, расположенных друг над другом, который остается в основном буфере в исходном порядке, позволяя функциям GSUB `'pres' / 'blws'` шрифта обрабатывать позиционирование нижних индексов. Поддерживается вложенность COENG.
  • No Repha: скрипты кхмерского языка не формируют визуальный элемент Repha, поэтому Ra + COENG + Consonant остается в исходном порядке, вместо того чтобы поворачиваться к концу слога.
  • В соответствии с Unicode 16.0 §16.4 (кхмерский язык) и спецификацией форматирования OpenType для кхмерского языка.

2026-05-23 Version 2.120.8

  • PAdES adbe-revocationInfoArchival CMS подписанный атрибут (PAdES Phase 9): генерирует приватный OID компании Adobe 1.2.840.113583.1.1.8, содержащий значения отзыва CRL и OCSP внутри самой цифровой подписи CMS. Adobe Acrobat отдает предпочтение этому атрибуту при проверке подписи на предмет отзыва, опережая поиск в словаре DSS и сетевые запросы OCSP/CRL - это критически важно для PDF-документов, которые можно проверить в автономном режиме, и обеспечивает лучшую совместимость с Adobe Acrobat.
  • Добавлены новые поля в `THPDFCMSSignOptions`:
    • AdobeCRLsDER: массив TBytes - каждый элемент является одним DER-объектом `CertificateList` (RFC 5280), в том же формате, что и потоки `CRLs` в DSS.
    • AdobeOCSPsDER: массив TBytes - каждый элемент является одним объектом SEQUENCE `BasicOCSPResponse` (RFC 6960 §4.2.1) в формате DER. Обратите внимание: это *не* внешний объект `OCSPResponse` - вызывающие процедуры, работающие с полными объектами `OCSPResponse`, должны сначала извлечь последовательность байтов `responseBytes.response` в виде строки OCTET, чтобы получить `BasicOCSPResponse`.
  • Активация: атрибут, который выдается, когда хотя бы один из двух массивов не пуст. Значение по умолчанию – пустой (оба массива), что обеспечивает стабильность на уровне байтов в версии v2.120.7.
  • ASN.1 DER в соответствии со спецификацией Adobe: RevocationInfoArchival ::= SEQUENCE { crl [0] EXPLICIT SEQUENCE OF CRL OPTIONAL, ocsp [1] EXPLICIT SEQUENCE OF BasicOCSPResponse OPTIONAL, otherRevInfo [2] EXPLICIT SEQUENCE OF OtherRevInfo OPTIONAL }. HotPDF использует [0] и [1]; [2] (otherRevInfo для систем отзыва, отличных от X.509) остается за пределами данной реализации.
  • Форма провода (оба ветвления заполнены): 30 A0 30 <...> A1 30 <...>
  • **Совместно используется со словарем DSS:** этот атрибут является *параллельным* (а не заменой) словарю PAdES-B-LT DSS (элементы уровня каталога /DSS /Certs /OCSPs /CRLs /VRI, представленные в версии v2.110.0). Строгие валидаторы PAdES (EU DSS, mTOM) обычно учитывают DSS; Adobe Acrobat учитывает adbe-revocationInfoArchival. Для максимальной совместимости, заполните оба уровня одинаковыми байтами CRL / OCSP с помощью AddPAdESDSSCRL / AddPAdESDSSOCSP и AdobeCRLsDER / AdobeOCSPsDER.
  • Обертка `HPDFCMSBuildSignedData` с 4 аргументами обнуляет новые поля, чтобы обеспечить сохранение байтовой идентичности устаревших пакетов CMS.
  • В соответствии со ссылками: Adobe Acrobat PDF Reference, RFC 5280 (CRL), RFC 6960 (OCSP).

2026-05-23 Version 2.120.7

  • PAdES content-time-stamp, подписанный с использованием CMS, атрибут (PAdES Phase 8): генерируется 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), содержащий предварительный токен времени (TimeStampToken) в соответствии с RFC 3161, который подтверждает, что содержимое документа существовало в момент, заявленный TSA, *до* того, как подписант подписал его. Отличается от signature-time-stamp (неподписанный атрибут Phase 4, добавляется после подписания).
  • Добавлено новое поле `THPDFCMSSignOptions`: `GetContentTimeStamp: THPDFCMSTimestampCallback`. Реализована зеркальная структура функции `GetSignatureTimeStamp`, как в версии v2.120.3. HotPDF вызывает обратный вызов с хешем SHA-256 документа (тот же хеш, что и атрибут `messageDigest`), и встраивает полученный `TimeStampToken` в формате DER в качестве значения атрибута `content-time-stamp` внутри `SignedAttributes`.
  • По умолчанию, nil означает, что метка времени не генерируется. Если вызывающей стороне требуется метка времени, она должна указать функцию, которая реализует TSA (Time-Stamping Authority) в соответствии с RFC 3161 через HTTP. Если возвращается пустой объект TBytes, операция пропускается без ошибок (обеспечивается корректная работа в случае недоступности TSA).
  • **Бесплатные конечные точки TSA** (не требуется подписка) для случаев использования, не подпадающих под определенные критерии: http://timestamp.digicert.com, http://timestamp.sectigo.com, http://timestamp.globalsign.com/tsa/r6advanced1, https://freetsa.org/tsr, http://timestamp.apple.com/ts01. Для сценариев, соответствующих требованиям eIDAS, требуется коммерческая QTSA; подписание для неюридических целей работает с бесплатными конечными точками (с ограничениями по скорости, но достаточными для типичных рабочих процессов).
  • Callback contract: вызывается один раз для каждой операции подписи. Перед тем, как атрибуты SignedAttributes будут зафиксированы, байты TST становятся частью данных, которые подписываются, поэтому сама подпись охватывает контент и временную метку. Именно поэтому это атрибут, подписанный, а не временная метка подписи, которая не подписана и находится в unsignedAttrs после подписи.
  • Набор оберток `HPDFCMSBuildSignedData` с 4 аргументами устанавливает `GetContentTimeStamp:=nil`, чтобы пакеты CMS старого формата оставались байтово идентичными.
  • Обязанности вызывающей стороны: для PAdES-заполнителей требуются данные `ContentsBytes`, объем которых должен быть достаточным для подписи и временной метки содержимого (TST) (обычно от 4 до 8 КБ). Для рабочих процессов B-T, объединяющих временную метку содержимого и временную метку подписи, необходимо учитывать обе временные метки. В случае использования `AddPAdESSignatureField(Profile='B-T')`, значение по умолчанию в 16 КБ обычно достаточно для большинства комбинаций.
  • В соответствии с ETSI EN 319 122-1 V1.2.1 §5.2.8, RFC 3161 §6 и RFC 5126 §5.11.4.

2026-05-23 Version 2.120.6

  • PAdES signer-attributes-v2 **signedAssertions [2]** ветка (PAdES Phase 7): закрывает третье и последнее поле SignerAttributeV2 (необязательное). Позволяет подписывающему лицу добавлять идентифицированные OID подписанные утверждения (SAML 2.0 Assertions, JWT токены в компактной форме, OAuth-подтверждения, токены подтверждения, специфичные для организации) внутрь цифровой подписи CMS.
  • Добавлена новая запись `THPDFSignedAssertion`: `SignedAssertionID` (точечный OID, идентифицирующий тип утверждения) плюс `AssertionBody: TBytes` (предварительно закодированные байты ANY, определенные схемой OID, обычно строка байтов, содержащая XML SAML или компактную форму JWT). Если `AssertionBody` пуст, поле ANY опускается, оставляя только `signedAssertionID` (что соответствует спецификации для утверждений типа boolean, зарегистрированных по OID).
  • Добавлено новое поле `THPDFCMSSignOptions`: `SignedAssertions: массив объектов типа THPDFSignedAssertion`. Поддерживается несколько проверок; HotPDF оборачивает последовательность в `[2] EXPLICIT` (тег `0xA2`).
  • Теперь условие, при котором генерируется `SignerAttributeV2`, срабатывает для любого из трех необязательных полей. Заполнение всех трех полей приводит к следующему: `SignerAttributeV2 SEQUENCE { [0] claimed..., [1] certified..., [2] signedAssertions... }` в указанном порядке в спецификации.
  • Согласно стандарту ASN.1, определенному в ETSI EN 319 122-1 §5.2.6: SignedAssertion ::= SEQUENCE { signedAssertionID OBJECT IDENTIFIER, signedAssertion ANY DEFINED BY signedAssertionID OPTIONAL }. Формат данных для одного утверждения с содержимым: A2 30 30 06 .
  • Использует функцию `CMSEncodeOIDFromString` (версия v2.120.1) для кодирования идентификаторов, обеспечивая поддержку любого идентификатора, представленного в виде точек.
  • Обертка `HPDFCMSBuildSignedData` с 4 аргументами обнуляет новое поле, чтобы обеспечить сохранение байтовой идентичности старых пакетов CMS.
  • 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.
  • В соответствии с ETSI EN 319 122-1 V1.2.1 §5.2.6 и приложением A.1.

2026-05-23 Version 2.120.5

2026-05-23 Version 2.120.4

2026-05-23 Version 2.120.3

  • PAdES signature-time-stamp CMS, атрибут без подписи (PAdES Phase 4): генерируется id-aa-signatureTimeStampToken (OID 1.2.840.113549.1.9.16.2.14, RFC 3161 §6 + ETSI EN 319 122-1 §5.3) внутри набора [1] IMPLICIT unsignedAttrs. Обеспечивает путь signature-time-stamp для PAdES-B-T, сервиса доверенной временной отметки (Таблица 1: B-T должен быть предоставлен через signature-time-stamp или document-time-stamp).
  • Добавлен новый анонимный тип метода `THPDFCMSTimestampCallback`: `reference to function(const SigValueSHA256: TBytes): TBytes`. HotPDF вызывает этот метод обратного вызова, передавая ему SHA-256 хэш значения `SignerInfo.signatureValue` (согласно RFC 3161, раздел 2.4.2, "messageImprint"), и использует возвращенный `TimeStampToken` в формате DER в качестве значения атрибута.
  • Добавлено новое поле `THPDFCMSSignOptions`: `GetSignatureTimeStamp`. Значение по умолчанию – `nil`, что означает отсутствие временной метки. В этом случае, вызывающие функции PAdES-B-T должны предоставлять замыкание, которое управляет взаимодействием с сервером времени (TSA) в соответствии с HTTP/RFC 3161 и возвращает байты временной метки (TST). Если возвращается пустая последовательность байтов, операция пропускается без ошибки (например, если сервер TSA недоступен, но подпись все равно должна быть создана).
  • Сетевые функции, аутентификация и обработка учетных записей TSA остаются в вызывающем коде; HotPDF просто передает результат в атрибут `unsignedAttrs`. Это хорошо сочетается с существующим размером заполнителя `AddPAdESSignatureField(Profile='B-T', ContentsBytes >= 16384)`.
  • В бинарном представлении ASN.1, структура `SignerInfo SEQUENCE` теперь может опционально содержать заключительный блок `[1] IMPLICIT SET OF Attribute` (тег `0xA1`), содержащий один атрибут `signature-time-stamp`, значение которого является точно таким, как указано вызывающей стороной в `TimeStampToken ContentInfo`.
  • Набор оберток `HPDFCMSBuildSignedData` с 4 аргументами устанавливает `GetSignatureTimeStamp:=nil`, чтобы устаревшие пакеты CMS оставались байтово идентичными.
  • В соответствии с RFC 3161 §6 + ETSI EN 319 122-1 §5.3 + EN 319 142-1 V1.2.1 §6.3 Таблица 1, примечание q (B-T может использовать либо временную метку, полученную во время подписания, либо временную метку, полученную во время создания документа, для обеспечения доверия к времени).

2026-05-23 Version 2.120.2

  • PAdES commitment-type-indication CMS Добавлена поддержка атрибута SignedAttribute (PAdES Phase 3): генерируется атрибут 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), который указывает тип обязательства, которое подписывающая сторона берет на себя с помощью подписи (например, подтверждение подлинности / получения / доставки / отправителя / одобрения / создания).
  • Добавлен новый перечисляемый тип `THPDFCommitmentType`: `ctNone` (по умолчанию, подавляет атрибут), `ctProofOfOrigin`, `ctProofOfReceipt`, `ctProofOfDelivery`, `ctProofOfSender`, `ctProofOfApproval`, `ctProofOfCreation` (шесть стандартных OID `id-cti-ets-*` из RFC 5126 §5.11.1, диапазон `1.2.840.113549.1.9.16.6.{1..6}`), и `ctCustom` (вызывающая сторона предоставляет произвольный OID через новое поле `CommitmentTypeOID`).
  • Активация: происходит каждый раз, когда THPDFCMSSignOptions.CommitmentType не равен ctNone. Значение по умолчанию, равное пустому, обеспечивает стабильность на уровне байтов в версии v2.120.1 для вызывающих сторон, которые не выбрали эту опцию.
  • **Обязанности вызывающей стороны (PAdES Часть 1 §6.3 Таблица 1, примечание d):** при указании типа обязательства, поле `Reason` в словаре подписи должно отсутствовать (взаимное исключение). HPDFCMS не отслеживает состояние словаря подписи; вызывающая сторона выбирает один из вариантов, используя `AddPAdESSignatureField(Reason='', ...)` вместе с `CommitmentType` или, если `CommitmentType=ctNone`, указывая `Reason`.
  • Структура ASN.1 DER: CommitmentTypeIndication SEQUENCE { commitmentTypeId OBJECT IDENTIFIER }. `CommitmentTypeQualifier` (RFC 5126 §5.11.2) опущена, поскольку шесть стандартных id-cti-ets-* OID не определяют квалификаторы. Пользовательские объекты, требующие квалификаторов, могут расширить вспомогательный модуль.
  • Обертка `HPDFCMSBuildSignedData` с 4 аргументами обнуляет новое поле `CommitmentType`, чтобы старые пакеты CMS оставались байтово идентичными версии v2.119.27.
  • В соответствии с ETSI EN 319 122-1 §5.2.3 + RFC 5126 §5.11 + ETSI EN 319 142-1 V1.2.1 §6.3, таблица 1, примечание d.

2026-05-23 Version 2.120.1

  • PAdES signature-policy-identifier CMS Добавлена поддержка атрибута SignedAttribute (этап 2 PAdES): генерируется атрибут 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), который указывает политику подписи, использованную для создания подписи. Обязателен для PAdES-E-EPES (Часть 2 V1.2.1 §5.4 Таблица 2: должен присутствовать); может присутствовать во всех остальных уровнях PAdES.
  • Добавлены новые поля в структуру `THPDFCMSSignOptions`: `SignaturePolicyOID` (строка, представляющая dotted-OID политики), `SignaturePolicyHash` (хеш политики), `SignaturePolicyHashAlgOID` (OID алгоритма хеширования, по умолчанию SHA-256, если не указан) и `SignaturePolicyURI` (необязательный квалификатор SPuri в соответствии с RFC 5126 §5.8.1, OID `1.2.840.113549.1.9.16.5.1`, указывающий на URL-адрес документа политики).
  • Активация: атрибут политики выдается только в том случае, если и `SignaturePolicyOID`, и `SignaturePolicyHash` заполнены вызывающей стороной. Если значения по умолчанию не указаны, атрибут подавляется, что обеспечивает стабильность на уровне байтов для существующих пользователей при использовании версии v2.120.0.
  • Новая функция `CMSEncodeOIDFromString` кодирует произвольные OID, представленные в точечной нотации, в формат DER в соответствии с X.690 §8.19 (первые два элемента объединяются как `40*arc1 + arc2`, последующие элементы используют систему счисления 128 и битами продолжения). OID политик специфичны для конкретного бизнеса, поэтому производитель не может закодировать их как литеральные байты.
  • ASN.1 DER структура: SignaturePolicyId SEQUENCE { sigPolicyId OBJECT IDENTIFIER, sigPolicyHash OtherHashAlgAndValue [, sigPolicyQualifiers SEQUENCE OF SigPolicyQualifierInfo] }. Квалификатор SPuri оборачивает URL в виде IA5String (тег 0x16) внутри объекта SigPolicyQualifierInfo.
  • Совместимость: версии v2.120.0, использующие новые поля политики, обеспечивают идентичный вывод, даже если эти поля не были заполнены. Обертка `HPDFCMSBuildSignedData` с четырьмя аргументами обнуляет новые поля, чтобы существующие пакеты CMS оставались неизменными.
  • В соответствии с ETSI EN 319 122-1 §5.2.9 + ETSI EN 319 142-2 V1.2.1 §5.4 Таблица 2 + RFC 5126 §5.8.

2026-05-23 Version 2.120.0

2026-05-23 Version 2.119.77

  • Добавлен модуль для формирования текста на сингальском языке (этап 8f.8). Сингальский язык ('sinh', U+0D80-U+0DFF) стал восьмым зарегистрированным индийским языком. Добавлены новые методы `ApplySinhalaReorder` и `GetSinhalaCategory` для THotPDF.
  • Сиддага: реализована поддержка Repha (Ra=U+0DBB + Halant=U+0DCA AL-LAKUNA); три пред-базовых матры (E=U+0DD9, EE=U+0DDA, AI=U+0DDB) — уникально, так как имеет три пред-базовых матры; 3 разделенные матры (U+0DDC O, U+0DDD OO, U+0DDE AU) с канонической разбивкой Unicode; U+0DDD OO состоит из трех частей (E + AA + AL-LAKUNA).
  • `ApplyIndicReorder` теперь поддерживает синггальский язык, обеспечивая прозрачную работу (реестр IndicScripts теперь представляет собой массив с индексами от 0 до 7).
  • 21 новых тестов DUnitX. Всего 187 из 187 тестов успешно пройдены на Win32 и Win64.
  • В соответствии со стандартом Unicode 16.0, раздел 12.11 (сингхальский язык), и спецификацией формирования текста OpenType для сингхальского языка.

2026-05-23 Version 2.119.76

  • Добавлена поддержка формирования текста на языке малаяли (Phase 8f.7). Малаяли ('mlym', U+0D00-U+0D7F) стал седьмым зарегистрированным индийским шрифтом. Добавлены новые методы `ApplyMalayalamReorder` и `GetMalayalamCategory` для `THotPDF`.
  • Функции для языка малаялам: реализован символ Repha (Ra=U+0D30 + Halant=U+0D4D, CHANDRAKKALA); I-matra (U+0D3F) имеет структуру, аналогичную тамильскому языку (уникально по сравнению с Devanagari/Bengali/Gujarati, где она находится перед базовым символом); префиксные символы E/EE/AI; 3 раздельных matra (U+0D4A O / U+0D4B OO / U+0D4C AU) с канонической декомпозицией префикса + суффикса; chillu letters (U+0D54-U+0D56, U+0D7A-U+0D7F) и DOT REPH (U+0D4E) классифицированы как согласные.
  • `ApplyIndicReorder` теперь поддерживает малаялам, обеспечивая прозрачную работу (реестр IndicScripts теперь представляет собой массив с индексами от 0 до 6).
  • Включено 21 новый тест DUnitX, охватывающий категорию chillu/DOT-REPH. Всего 166 из 166 тестов успешно пройдены на Win32 и Win64.
  • В соответствии со стандартом Unicode 16.0, раздел 12.10 (малаялам), и спецификацией форматирования OpenType для малаяли.

2026-05-23 Version 2.119.75

  • Добавлен компонент для обработки текста на каннада (план разработки движка GSUB, фаза 8f.6). Каннада ('knda', U+0C80-U+0CFF) стала шестым зарегистрированным индийским шрифтом. Добавлены новые публичные методы ApplyKannadaReorder и GetKannadaCategory для объекта THotPDF.
  • В языке каннада присутствуют символы Repha (Ra=U+0CB0 + Halant=U+0CCD), как и в деванагари, бенгали, гуджарати и телугу. Как и в телугу, в каннада нет префиксных диакритических знаков; каждый диакритический знак в каннада находится либо над базой, либо под базой, либо после базы, либо разделен.
  • Разделены матры с использованием канонической декомпозиции Unicode 16.0: U+0CC0 II → U+0CBF (сверху) + U+0CD5 (после); U+0CC7 EE → U+0CC6 (сверху) + U+0CD5 (после); U+0CC8 AI → U+0CC6 + U+0CD6 (оба сверху); U+0CCA O → U+0CC6 (сверху) + U+0CC2 (после); U+0CCB OO состоит из трех частей: U+0CC6 (сверху) + U+0CC2 (после) + U+0CD5 (после) — первая трехчастная матра, обработанная семейством шейперов Phase 8f.
  • Вышебазовые ма́тры (R3): I (U+0CBF), E (U+0CC6), AU (U+0CCC), знак длительности AI (U+0CD6). Нижебазовые ма́тры (R4): гласные R/RR (U+0CC3-U+0CC4), гласные L/LL ма́тры (U+0CE2-U+0CE3). Послебазовые ма́тры (R5): AA (U+0CBE), U/UU (U+0CC1-U+0CC2), знак длительности, расположенный после базовой буквы (U+0CD5).
  • `ApplyIndicReorder` диспетчер теперь автоматически определяет язык каннада через реестр (теперь массив[0..5]).
  • Тесты: Добавлено 21 новый тестовый случай DUnitX, включая все 5 случаев раздельных диакритических знаков, а также специальную проверку для трехкомпонентных символов "OO". Всего 145 из 145 тестов успешно пройдены на Win32 и Win64.
  • В соответствии с Unicode 16.0 §12.9 (для языка каннада) и спецификацией форматирования OpenType для языка каннада.

2026-05-23 Version 2.119.74

  • Добавлена поддержка формирования текста на языке телугу (план развития движка GSUB, фаза 8f.5). Язык телугу ('telu', U+0C00-U+0C7F) стал пятым зарегистрированным индийским шрифтом. Добавлены новые публичные методы ApplyTeluguReorder и GetTeluguCategory для объекта THotPDF.
  • В языке Телугу используется система знаков Repha (Ra=U+0C30 + Halant=U+0C4D), аналогичная той, что используется в деванагари, бенгали и гуджарати. В отличие от всех предыдущих индийских письменностей, в языке Телугу отсутствуют базовые диакритические знаки; каждый диакритический знак в языке Телугу находится либо над базовой буквой, либо под ней, либо разделен с ней.
  • Вышебазовые матры (R3): AA/I/II/E/EE/O/OO/AU плюс знак длительности. U+0C55. Нижебазовые матры (R4): U/UU/Гласный R/RR (U+0C41-U+0C44), знак длительности для AI (U+0C56), гласные матры L/LL (U+0C62-U+0C63).
  • 1. Разделение символа matra: символ U+0C48 AI при переупорядочивании раскладывается на U+0C46 (E над базовой строкой) + U+0C56 (знак длительности AI под базовой строкой).
  • `ApplyIndicReorder` диспетчер теперь автоматически определяет телугу, используя информацию из реестра (теперь в массиве с индексами от 0 до 4).
  • Тесты: Добавлено 17 новых тестовых случаев DUnitX. Всего 124 из 124 тестов успешно пройдены на Win32 и Win64.
  • В соответствии со стандартом Unicode 16.0, раздел 12.8 (телугу), и спецификацией форматирования OpenType для языка телугу.

2026-05-23 Version 2.119.73

  • Добавлена поддержка языка тамильский (план развития движка GSUB, фаза 8f.4). Тамильский ('taml', U+0B80-U+0BFF) стал четвертым зарегистрированным индийским алфавитом. Добавлены новые публичные методы ApplyTamilReorder и GetTamilCategory для объекта THotPDF.
  • Отличия тамильского письма от других письменностей брахми: В тамильском письме отсутствует символ Repha (в традиционной тамильской письменности он не формируется визуально); I-matra (U+0BBF) располагается ПОСЛЕ основной буквы, что является уникальной особенностью среди письменностей брахми; II (U+0BC0) располагается над основной буквой; E/EE/AI (U+0BC6-U+0BC8) располагаются перед основной буквой; существуют три раздельные матры (U+0BCA O = U+0BC6+U+0BBE, U+0BCB OO = U+0BC7+U+0BBE, U+0BCC AU = U+0BC6+U+0BD7).
  • В тамильском языке символ Halant имеет имя PULLI в кодовой позиции U+0BCD. Функция `ApplyIndicReorder` прозрачно определяет тамильский язык через реестр (теперь в массиве с индексами от 0 до 3).
  • Тесты: Добавлено 20 новых тестовых сценариев DUnitX. Всего 107 из 107 тестов успешно пройдены на Win32 и Win64.
  • В соответствии со стандартом Unicode 16.0 §12.7 (для языка тамильский) и спецификацией формирования текста OpenType для языка тамильский.

2026-05-23 Version 2.119.72

  • Добавлен компонент форматирования для языка гуджарати (план разработки движка GSUB, фаза 8f.3). Гуджарати ('gujr', U+0A80-U+0AFF) становится третьим зарегистрированным индийским алфавитом после деванагари и бенгали. Добавлены новые публичные методы ApplyGujaratiReorder и GetGujaratiCategory в классе THotPDF.
  • Измените порядок правил: R1 Repha (Ra=U+0AB0 + Halant=U+0ACD), R2 pre-base (U+0ABF I), R3 above-base (U+0AC5 CANDRA E, U+0AC7 E, U+0AC8 AI — обратите внимание, что в гуджарати надбазовая позиция аналогична деванагари, а не предбазовая, как в бенгали), R4 below-base (U+0AC1-U+0AC4, U+0AE2-U+0AE3), R5 post-base (U+0ABE AA, U+0AC0 II, U+0AC9 CANDRA O, U+0ACB-U+0ACC O/AU). Отсутствуют разделенные матры.
  • `ApplyIndicReorder` диспетчер прозрачно использует гуджарати через реестр `IndicScripts` (теперь массив[0..2]). Интеграция `BuildUnicode*FieldContent` работает с `sfIndicShaping`, обеспечивая поддержку гуджарати без каких-либо изменений в интеграции.
  • Тесты: Добавлено 18 новых тестовых случаев DUnitX, включая покрытие R3, чтобы различать обработку символов E/AI в гуджарати и бенгали. Всего 87 из 87 тестов успешно пройдены на Win32 и Win64.
  • В соответствии со стандартом Unicode 16.0, раздел 12.6 (гуджарати), и спецификацией форматирования OpenType для гуджарати.

2026-05-23 Version 2.119.71

  • Добавлен модуль форматирования бенгальского языка (план разработки движка GSUB, фаза 8f.2). Бенгальский ('beng', U+0980-U+09FF) становится вторым зарегистрированным индийским скриптом после деванагари. Добавлены новые публичные методы ApplyBengaliReorder и GetBengaliCategory для объекта THotPDF, аналогичные API для деванагари, представленному в фазе 8e.
  • Правила перестановки для бенгальского языка: R1 Repha (Ra=U+09B0 + Halant=U+09CD), R2 предударные матры (I=U+09BF, E=U+09C7, AI=U+09C8 — обратите внимание, что E/AI являются предударными в бенгальском языке, в отличие от деванагари, где они находятся над базой), R4 под базой (U+09C1-U+09C4, U+09E2-U+09E3), R5 после базовой (U+09BE, U+09C0, U+09D7). В основной части бенгальского блока нет матр, расположенных над базой.
  • Разделение матр: символы `U+09CB` Oo и `U+09CC` AU расширяются до своих визуальных компонентов во время переупорядочивания (U+09C7 + U+09BE / U+09C7 + U+09D7), чтобы конвейер GSUB видел их в канонических позициях "до" и "после".
  • `ApplyIndicReorder` диспетчер прозрачно направляет бенгальские символы в соответствующий раздел бенгальского языка; функции `BuildUnicode*FieldContent`, использующие `sfIndicShaping`, теперь поддерживают бенгальский язык наряду с деванагари, без каких-либо изменений в интеграции.
  • Тесты: Добавлено 18 новых тестовых сценариев DUnitX, охватывающих бенгальский язык (R1/R2/R4/R5), разделение символов, сохранение лигатур, поддержку смешанных систем письма, идемпотентность и эквивалентность диспетчеров. Всего 69 из 69 тестов успешно пройдены на Win32 и Win64.
  • В соответствии с Unicode 16.0 §12.2 (бенгальский язык) и спецификацией форматирования OpenType для бенгальского языка.

2026-05-23 Version 2.119.70

  • Обновление модуля формирования текста Devanagari (дорожная карта движка GSUB, фаза 8f.1): `ApplyDevanagariReorder` теперь применяет полный набор из 5 правил перестановки (R1 Repha + R2 pre-base + R3 above-base + R4 below-base + R5 post-base) вместо подмножества, состоящего только из R1 и R2, которое использовалось в версии v2.119.55. Порядок кластеров выводится в соответствии со слогами: `[pre-matras] + [base + halant + nukta + bindu/visarga/modifier] + [above-matras] + [below-matras] + [post-matras] + [Repha]`.
  • Сохранение лигатур: группы согласных-суффиксов-согласных остаются сгруппированными в базовом блоке; переупорядочивание затрагивает только матры и Repha. Выполняется за один проход и является идемпотентной операцией.
  • Изменения в поведении по сравнению с версией v2.119.69: для слогов, содержащих верхние/нижние/ последовательные диакритические знаки (или кластеры диакритических знаков), поток байтов PDF теперь отражает канонический порядок расположения. Визуальная отрисовка после операций GSUB/GPOS остается неизменной. Входные данные, содержащие только R1 Repha или R2 pre-base I-matra (подмножество v2.119.55), генерируют идентичный по байтам вывод.
  • Тесты: Добавлено 8 новых тестовых сценариев DUnitX, охватывающих отдельные случаи R3, R4 и R5, порядок нескольких диакритических знаков, сохранение лигатур при использовании диакритических знаков, комбинации Repha с верхними и нижними диакритическими знаками, а также идемпотентность для нескольких диакритических знаков. Всего 51 из 51 теста успешно пройдены на Win32 и Win64.
  • В соответствии с Unicode 16.0 §12.1 (Devanagari) и спецификацией форматирования Devanagari OpenType.

2026-05-23 Version 2.119.69

  • Инфраструктура форматирования текста для индийских языков (дорожная карта движка GSUB, фаза 8f.0): была переработана предварительная обработка упорядочивания для Devanagari, версии v2.119.55 / v2.119.67, в универсальную систему вызовов. Новые типы данных `TIndicScriptInfo`, `TIndicCategoryFunc`, `TIndicFindSyllableFunc` и `TIndicReorderFunc`, а также новый реестр `IndicScripts`, позволяют подключать новые индийские языки с помощью указателей на функции.
  • Новый публичный метод `ApplyIndicReorder(Wide)` передает каждый символ Unicode из `Wide` соответствующему зарегистрированному скрипту и применяет функции перестановки слогов, определенные для этого скрипта. Не относящийся к индийским языкам контент передается без изменений.
  • Функции `BuildUnicode*FieldContent` теперь вызывают `ApplyIndicReorder` (вместо обертки, предназначенной только для Devanagari), когда `sfIndicShaping` находится в `FShapingFeatures`. В версии 8f.0 реализована поддержка только Devanagari; в последующих версиях 8f.2 - 8f.10 добавлены бенгали, гуджарати, тамильский, телугу, каннада, малаялам, сингальский, кхмерский и бирманский языки, при этом интеграция не была изменена.
  • Существующая функция `ApplyDevanagariReorder` сохранена в качестве оболочки, предназначенной только для языка Devanagari, для обеспечения обратной совместимости с версией v2.119.55. Результат работы функции не изменился по сравнению с версией v2.119.67.
  • В соответствии с Unicode 16.0 §12 (письменности Южной Азии) и ISO 32000-1 §9.10.

2026-05-22 Version 2.119.68

  • Фаза 8c.6 — Генерация идентификаторов GID на стороне производителя с использованием сопоставления синтетических кодовых точек из частной области: два новых публичных метода в THotPDF позволяют вызывающим сторонам генерировать идентификаторы GID, которые не имеют естественного кодового значения Unicode, путем выделения синтетических кодовых точек PUA (U+E000-U+F8FF) по требованию. Метод AssignSyntheticCodepointForGID (GID; out SyntheticCP): Boolean выделяет следующий доступный слот PUA, отражает это назначение в FUnicodeCpToGid + FAcroFormUnicodeAdvances + новой таблице поиска FUnicodeSyntheticCpForGID для каждого GID, чтобы существующий конвейер шестнадцатеричного кодирования на стороне производителя выдавал синтетическую кодовую точку в виде токена из четырех шестнадцатеричных цифр, который потребительский ридер разрешает через /CIDToGIDMap для получения заменяющего глифа. Метод GetSyntheticCodepointForGID (GID): Word запрашивает существующие назначения (возвращает 0, если синтетический код не назначен). Оба метода являются идемпотентными — повторные вызовы с одним и тем же GID возвращают один и тот же синтетический кодовую точку.
  • Разблокирована возможность генерации шрифтами символов GSUB, которые не имеют кодовых точек Unicode Presentation Form: это касается кластерных форм деванагари (где вывод 'akhn' / 'rphf' / 'pres' / 'blws' / 'psts' / 'haln' обычно попадает во внутренние GID шрифта), стилистических альтернатив ('salt' / 'ss01-20' без кодовых точек), дискреционных лигатур ('dlig' / 'hlig', специфичные для шрифта глифы) и последовательностей вариаций идеограмм CJK. В сочетании с API движка GSUB версии v2.119.43-50 и функцией подмножества MarkUnicodeGlyphUsed версии v2.119.50, теперь вызывающие функции могут создавать полные конвейеры форматирования на стороне производителя, которые генерируют произвольные GID заменяемых символов через существующий шестнадцатеричный конвейер, основанный на кодовых точках.
  • Срок жизни состояния: синтетические отображения сохраняются до тех пор, пока не будет вызвана функция RegisterUnicodeTTF или не будет запущена функция BeginDoc (обе функции сбрасывают все параметры шрифта, включая синтетическую таблицу). Диапазон PUA U+E000-U+F8FF предоставляет 6400 слотов, что достаточно для любого практического набора замен GSUB шрифта. Обратное отображение CMap ToUnicode является ответственностью вызывающей стороны — синтетические символы PUA не имеют исходных символов для обратного отображения; вызывающие стороны, обеспокоенные извлечением текста, должны заключать генерируемый текст в PDF с использованием помеченного содержимого с атрибутом /ActualText, указывающим исходные символы. PDF-файлы, в которых вызывающие стороны не вызывают функцию AssignSyntheticCodepointForGID, будут идентичны по байтам выходным данным v2.119.67 (новые методы являются stateless-запросами / помощниками для явного выделения; они не имеют автоматических побочных эффектов). Этот коммит завершает дорожную карту GSUB, фаза 8, матрица возможностей.

2026-05-22 Version 2.119.67

  • Автоматическое применение предварительного этапа переупорядочивания Devanagari (дорожная карта движка GSUB, фаза 8e): три вспомогательные функции BuildUnicode*FieldContent теперь автоматически вызывают метод ApplyDevanagariReorder версии 2.119.55, когда sfIndicShaping включен в FShapingFeatures. Этот предварительный этап проходит по входным данным слева направо, применяя два специфичных для Devanagari переупорядочивания (перемещение Repha для Ra-Halant в начале слога и перемещение I-matra U+093F в начало слоговой группы), чтобы поток выводимых кодовых точек соответствовал визуальному порядку чтения. Затем движок GSUB читателя применяет цепочку форматирования Indic ('nukt' / 'akhn' / 'rphf' / 'rkrf' / 'pref' / 'half' / 'vatu' / 'cjct' / 'pres' / 'blws' / 'abvs' / 'psts' / 'haln') к переупорядоченным кодовым точкам для создания окончательных глифов кластеров.
  • В рамках 8-й фазы, версия "e" обеспечивает только переупорядочивание на стороне генератора. Применение цепочек GSUB на стороне генератора (когда генератор выполняет формирование кластеров во время создания PDF-файла, а не полагается на интерпретатор) отложено до фазы 8c.6, поскольку большинство замен GSUB для Devanagari приводят к использованию GID, специфичных для шрифта, без соответствующего символа в Unicode Presentation Form. В отличие от арабского/латинского алфавитов, где блоки Forms-A/Forms-B предоставляют символы, доступные через кодовые точки, для Devanagari нет эквивалентного диапазона Presentation Form в Unicode. Отображение синтетических кодовых точек PUA в фазе 8c.6 позволит реализовать GSUB на стороне генератора для Devanagari и других индийских/южно-азиатских скриптов, где GID, используемые для замены, специфичны для шрифта.
  • Содержимое, не относящееся к деванагари, проходит через функцию `ApplyDevanagariReorder` без изменений (эта функция обрабатывает только слоги деванагари; другие диапазоны символов выводятся без изменений). PDF-файлы, для которых вызывающие функции не отключают `sfIndicShaping` (по умолчанию), выводятся идентично версии v2.119.66. В сочетании с уровнем возможностей v2.119.55 (методы `GetDevanagariCategory` и `ApplyDevanagariReorder` теперь являются общедоступными), это изменение завершает интеграцию переупорядочивания деванагари на стороне генератора: вызывающие функции, которые включают `sfIndicShaping`, больше не должны предварительно переупорядочивать данные или вызывать `ApplyDevanagariReorder` вручную перед вызовом `BuildUnicode*FieldContent` — HotPDF делает это автоматически.

2026-05-22 Version 2.119.66

  • GSUB 'rclt' (автоматическая интеграция обязательных контекстных альтернатив): новый метод THotPDF.ApplyArabicGSUBContextualRefinement (широкий) аналогичен методу v2.119.63 ApplyArabicGSUBRefinement, но применяет контекстную подстановку (GSUB тип 5/6) с использованием API v2.119.47 ApplyContextualSubst вместо подстановки лигатур (тип 4). 'rclt' кодирует обязательные подстановки, зависящие от контекста, которые обычно используются в арабских шрифтах для дополнительных позиционных вариантов, выходящих за рамки сопоставления Forms-B статического анализатора v2.85.0, а также в шрифтах Юго-Восточной Азии/Индии для изменения формы кластеров на уровне кластера, в зависимости от соседнего контекста.
  • Обработка выходных данных переменной длины: в отличие от функции `ApplyLigatureSubstitution` (N идентификаторов GID на вход -> 1 заменяющий GID), функция `ApplyContextualSubst` может генерировать M заменяющих GID из N входных GID. Когда срабатывает контекстное правило, ВСЕ заменяющие GID должны быть доступны через точки кода Unicode Presentation Form, используя обратную таблицу cmap (FB00-FDFF + FE70-FEFF, сканируется около 770 точек кода), чтобы замена была применена; если у какого-либо заменяющего GID отсутствует обратное соответствие, входное окно остается неизменным (частичная генерация приведет к повреждению последовательности). Диапазон обратной таблицы cmap расширен для охвата Latin, Armenian и Hebrew Presentation Forms (FB00-FB4F), а также всех диапазонов арабского алфавита, чтобы можно было генерировать заменяющие символы 'rclt' из любого алфавита.
  • Добавлен новый член перечисления `THPDFShapingFeature` с именем `sfContextualAlternates` (добавлен в конец для обратной совместимости — существующие вызывающие функции, использующие `FShapingFeatures`, компилируются без изменений). Интегрирован в три вспомогательные функции `BuildUnicode*FieldContent`, которые используют `sfContextualAlternates` в `FShapingFeatures` (опционально, по умолчанию отключено). Это не зависит от `FAutoShapeArabic` — 'rclt' может применяться к неарабским скриптам (латинице, иврит, индийским). Замененные идентификаторы GID передаются через `MarkUnicodeGlyphUsed` для подсистемы создания шрифтов версии 2.84.0. Выполняется безопасная операция без изменений, если в шрифте нет правил 'rclt' или замененные идентификаторы GID не содержат кодовых точек Presentation Form. PDF-файлы, для которых вызывающие функции не используют `sfContextualAlternates`, генерируются с байтами, идентичными версии 2.119.65.

2026-05-22 Version 2.119.65

  • В рамках реализации дорожной карты движка GSUB, фаза 8b, реализован новый метод THotPDF.ApplyLatinLigatureRefinement (Wide), который аналогичен методу v2.119.63 ApplyArabicGSUBRefinement, но предназначен для латинских, армянских и еврейских алфавитных форм, представленных в диапазоне U+FB00-U+FB4F. Метод проходит по входной строке, создает параллельный массив GID с использованием FUnicodeCpToGid и запрашивает функцию GSUB 'liga' (стандартные лигатуры) шрифта через API v2.119.43-50 ApplyLigatureSubstitution для каждой позиции. Если происходит замена лигатуры И заменяющий GID доступен через кодовую точку алфавитной формы Unicode, окно исходной кодовой точки заменяется кодовой точкой заменяющего символа. Этот функционал интегрирован в три вспомогательные функции BuildUnicode*FieldContent (для однострочных, многострочных и комбинированных форм AcroForm /AP), и он активируется параметром sfStandardLigatures в FShapingFeatures (опционально, стабилен на уровне байтов, если не установлен).
  • Опциональный второй проход для 'clig' (контекстные лигатуры): если `sfContextualLigatures` также включен в `FShapingFeatures`, метод повторно обрабатывает результат, полученный после применения 'liga', применяя 'clig' для учета контекстных лигатур, специфичных для шрифта, помимо стандартных сочетаний fi / fl / ffi / ffl. Каждый сгенерированный идентификатор заменяемого глифа передается в `MarkUnicodeGlyphUsed` для компонента подмножества TTF версии v2.84.0. Обратная cmap представляет собой линейный просмотр примерно 80 кодовых точек (FB00-FB4F); замены редки, и затраты незначительны.
  • 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 для запроса информации о продвижении символов (план развития движка GSUB, фаза 8c.5): новый метод THotPDF.GetCodepointAdvance (CP: Cardinal) предоставляет доступ к кэшу /W версии v2.76.0, позволяя вызывающим программам, создающим собственные алгоритмы переноса слов, запрашивать реальное масштабированное значение продвижения для любого символа, полученное из таблицы hmtx шрифта через кэшированную cmap. После статической обработки лигатур v2.119.32 / v2.119.58 / v2.119.60 / v2.119.62 и уточнения GSUB на уровне GID v2.119.63, генерируются символы лигатур (LAM-ALEF FEF5-FEFC, YEH-HAMZA FBEA-FBFB, Allah FDF2, Bismillah FDFD), а также Presentation Forms, замененные GSUB, в FB50-FDFF / FE70-FEFF). Этот метод возвращает реальное значение продвижения глифа лигатуры (обычно меньше суммы значений продвижения исходных символов), чтобы бюджеты переноса строк вызывающих программ соответствовали результатам рендеринга на стороне клиента.
  • Улучшена эвристическая обработка многострочного содержимого поля Unicode: в предыдущей версии v2.65, в случае недоступности кэша (/W, например, при использовании пути RegisterUnicodeFontDict вместо RegisterUnicodeTTF), все символы с кодом >= U+2E80 считались широкими (1.0 em). Арабские символы в формах (FB50-FBFF - буквы формы A, FC00-FDFF - лигатуры формы A + Quranic FDF0-FDFD, FE70-FEFF - базовые формы B + LAM-ALEF) на самом деле являются узкими (в среднем ~0.55 em для большинства арабских шрифтов), а не широкими. В версии v2.119.64 эти три диапазона арабских символов направляются на путь для узких символов (0.5 em) в эвристической обработке, что исправляет случай, когда лигатуры арабского письма, генерируемые в рамках обработок v2.119.32 / v2.119.58 / v2.119.60 / v2.119.62 / v2.119.63, могли бы ошибочно иметь ширину 1.0 em, если кэш не был заполнен.
  • Возвращает 0 для обычного сценария, когда нет информации (шрифт не зарегистрирован, кэш еще не заполнен, кодовая точка выше BMP, кодовая точка не имеет глифа в cmap шрифта). Функция является чисто функциональной, не имеет побочных эффектов и ее безопасно вызывать из любого контекста после успешного выполнения RegisterUnicodeTTF. PDF-файлы, в которых загруженный шрифт имеет заполненный кэш /W и которые не используют новый метод запроса, генерируют вывод, идентичный по байтам версии v2.119.63. Этап 8c.5 завершает дорожную карту движка GSUB §8c, реализуя автоматическую конвейерную обработку арабских символов GSUB на стороне производителя на уровне возможностей. Этапы 8c.1-8c.5 вместе обеспечивают статические этапы постобработки (4 семейства лигатур) + обратное преобразование ToUnicode + уточнение GSUB на уровне GID + публичный запрос на продвижение, все это работает вместе, чтобы обеспечить точное соответствие байтам при отображении арабских лигатур на стороне производителя и на стороне потребителя.

2026-05-22 Version 2.119.63

  • Улучшения на уровне GID для GSUB 'rlig' (дорожная карта движка GSUB, фаза 8c.2): новый метод THotPDF.ApplyArabicGSUBRefinement (Wide) проходит по входной строке слева направо, создавая параллельный массив GID, используя кэшированную таблицу cmap (FUnicodeCpToGid), и на каждой позиции с ненулевым GID запрашивает функцию GSUB 'rlig' (обязательные лигатуры) шрифта через API ApplyLigatureSubstitution версии v2.119.43-50. Если происходит замена лигатуры И заменяющий GID доступен через кодовую точку Unicode для арабской презентационной формы (обратный просмотр таблицы cmap в диапазоне U+FB50-U+FDFF + U+FE70-U+FEFF, примерно 690 кодовых точек), окно исходной кодовой точки заменяется кодовой точкой заменителя. Заменяющие глифы также передаются в MarkUnicodeGlyphUsed для завершения работы подсистемы TTF версии v2.84.0.
  • Внедрено в три вспомогательные функции `BuildUnicode*FieldContent` сразу после статической цепочки обработки символов (LAM-ALEF / YEH-HAMZA / Allah / Bismillah) версий v2.85.0 / v2.119.32 / v2.119.58 / v2.119.60 / v2.119.62. Дополняет статическую таблицу, используя правила 'rlig', специфичные для шрифта, которые не включены в четыре жестко закодированных семейства шрифтов. Типичные примеры включают контекстные варианты в шрифтах персидского / урду / синдхи / курдского языков (Vazirmatn, Markazi Text, Lateef, Scheherazade, Amiri), которые соответствуют формам представления Unicode, выходящим за рамки набора LAM-ALEF / YEH-HAMZA / Allah / Bismillah. Работает только в том случае, если `FAutoShapeArabic` имеет значение true И `sfArabicGSUB` отсутствует в `FShapingFeatures` (механизм взаимной блокировки сохраняет путь "управляемый вызывающим" версии v2.119.59), И загруженный шрифт имеет таблицу GSUB.
  • Область действия: учитываются только те замены, GID которых доступны через кодовую точку Presentation Form с помощью cmap. Замены, специфичные для шрифта, которые приводят к произвольным GID (без обратного отображения кодовой точки), не могут быть выведены этим способом — для них требуется полная обработка на уровне GID в конвейере генерации, зарезервированном для Phase 8c.5+. Обратное отображение cmap — это линейный просмотр примерно 690 кодовых точек для каждой попытки замены; замены встречаются редко, поэтому затраты незначительны. PDF-файлы, в которых загруженный шрифт не содержит GSUB 'rlig' или у которых замены не имеют кодовых точек Presentation Form, генерируются с байтовым соответствием выходным данным v2.119.62 (в этих случаях метод является защитной операцией без фактического выполнения). В этой версии, механизм GSUB на стороне генератора получает возможность учитывать шрифт при формировании лигатур, что выходит за рамки жестко закодированной статической таблицы.

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.
  • CMap для преобразования в Unicode расширен на 28-й символ bfchar, который теперь отображает U+FDFD обратно в исходную последовательность из 22 символов (BEH + SEEN + MEEM + SPACE + ALEF + LAM + LAM + HEH + SPACE + ALEF + LAM + REH + HAH + MEEM + NOON + SPACE + ALEF + LAM + REH + HAH + YEH + MEEM). Теперь, при извлечении текста на стороне клиента (копирование/вставка/доступность), восстанавливается исходная фраза из 22 символов, а не отдельный лигатурный глиф, что завершает процесс преобразования для четырех семейств лигатур со статическими таблицами (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.
  • В этой версии добавлено: 8 записей для символов LAM-ALEF в диапазоне U+FEF5-U+FEFC (обязательная лигатура v2.119.32, 4 варианта ALEF × 2 формы) → пары символов LAM + ALEF / ALEF MADDA / ALEF HAMZA ABOVE / ALEF HAMZA BELOW; 18 записей для семейства YEH-HAMZA в диапазоне U+FBEA-U+FBFB (v2.119.58, включает начальные формы FBF8 и FBFB, которые автоматическая постобработка не создает, но пользователи могут использовать напрямую) → пары символов YEH-HAMZA + ALEF / AE / WAW / U / OE / YU / E / ALEF MAKSURA; 1 запись для символа Allah в позиции U+FDF2 (v2.119.60) → последовательность из четырех символов: ALEF + LAM + LAM + HEH. С этим обновлением, операции копирования/вставки и обеспечение доступности для трех семейств лигатур, использующих статические таблицы, завершены.
  • Для контента, не содержащего арабский текст, обеспечена стабильность размера: блок `bfchar` добавляет около 700 байт нескомпрессированного текста PostScript в поток CMap, который обычно сжимается алгоритмом `FlateDecode` до 150-200 байт. PDF-файлы, не содержащие арабский текст, по-прежнему используют ту же структуру потока `/ToUnicode`, причем расширение добавляется в один и тот же косвенный объект потока `FlateDecode`. Все клиентские ридеры (Adobe Reader, Foxit, PDF.js, Apple Preview и т.д.) корректно обрабатывают приоритет `bfchar` над `bfrange` и применяют обратное преобразование. Блок из 27 записей жестко закодирован в тексте CMap (не требуется индивидуальная настройка для каждого PDF-файла); в будущем, в фазе 8c.4, будут добавлены дополнительные записи `bfchar` для лигатуры `U+FDFD Bismillah`.

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

  • В рамках программы развития движка GSUB (8a фаза): новая перечисление THPDFShapingFeature и тип THPDFShapingFeatures определяют запланированные флаги функций для интеграции формирования текста на стороне производителя. Пять элементов перечисления: sfArabicGSUB (реализовано в этом выпуске), sfStandardLigatures (8b фаза, в будущем), sfContextualLigatures (8b фаза, в будущем), sfStylisticAlternates (8d фаза, в будущем) и sfIndicShaping (8e фаза, в будущем). THotPDF получает свойство ShapingFeatures типа THPDFShapingFeatures со значением по умолчанию [], (все функции отключены); в версиях v2.119.32-58, если свойство остается со значением по умолчанию, вызывающие функции получают выходные данные, идентичные по байтам.
  • sfArabicGSUB действует как блокировка для модуля формирования арабского текста на основе статической таблицы версии 2.85.0. Если sfArabicGSUB включен в ShapingFeatures, то три вспомогательные функции BuildUnicode*FieldContent (для однострочного, многострочного и комбинированного содержимого форм AcroForm /AP) полностью пропускают этап _ApplyArabicShaping — не происходит переписывания четырехпозиционных кодовых точек версии 2.85.0, не выполняется дополнительная обработка LAM-ALEF версии 2.119.32, не выполняется дополнительная обработка YEH-HAMZA + гласных версии 2.119.58. Вызывающая сторона отвечает за управление выбором арабского форматирования с помощью API движка GSUB версии 2.119.43-50 (SetGSUBScript ('arab') + GetSingleSubstituteGlyph для тегов функций 'init' / 'medi' / 'fina' / 'isol' + MarkUnicodeGlyphUsed для завершения работы подсистемы подмножества версии 2.84.0). В сочетании с sfArabicGSUB, вызывающие стороны, использующие шрифты Noto Sans Arabic / Amiri / Scheherazade / Markazi Text / и аналогичные арабские шрифты, теперь могут выполнять полное форматирование арабского текста на стороне шрифта на этапе создания, вместо использования статической таблицы в качестве резервного варианта.
  • 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

  • В версии v2.85.0 модуль формирования арабского текста, работающий на стороне сервера, теперь объединяет 8 пар лигатур, закодированных в блоке Arabic Presentation Forms-A (U+FBEA-U+FBFB), в отдельные символы лигатур после обработки 4-позиционным алгоритмом и после этапа обработки LAM-ALEF (версия v2.119.32). Используется та же модель и интеграция, что и для LAM-ALEF (обязательная статическая таблица замен, вывод 2 форм для каждой лигатуры). Обрабатываемые пары: YEH-HAMZA + ALEF -> FBEA/FBEB (стандартный арабский / персидский / урду), YEH-HAMZA + AE U+06D5 -> FBEC/FBED (кашмирский / уйгурский), YEH-HAMZA + WAW -> FBEE/FBEF (стандартный арабский), YEH-HAMZA + U U+06C7 -> FBF0/FBF1 (уйгурский / казахский / киргизский), YEH-HAMZA + OE U+06C6 -> FBF2/FBF3 (то же самое), YEH-HAMZA + YU U+06C8 -> FBF4/FBF5 (то же самое), YEH-HAMZA + E U+06D0 -> FBF6/FBF7 (то же самое), YEH-HAMZA + ALEF MAKSURA -> FBF9/FBFA (стандартный арабский).
  • YEH-HAMZA сопоставляется в исходном виде (U+0626) или в любой из своих измененных форм версии v2.85.0 (FE89 isol, FE8A final, FE8B init, FE8C medial); следующая гласная буква сопоставляется в исходном виде или в любом из своих вариантов формы A версии v2.119.57 (FBD7-FBD8 для U, FBD9-FBDA для OE, FBDB-FBDC для YU, FBE4-FBE7 для E) или в вариантах формы B версии v2.85.0 (FE8D-FE8E для ALEF, FEED-FEEE для WAW, FEEF-FEF0 для ALEF MAKSURA). Выбор окончательной формы (базовый + 1) следует правилу LAM-ALEF: когда YEH-HAMZA преобразован в окончательную форму FE8A или медиальную форму FE8C (то есть, за ним следует двойная связующая буква), лигатура выводится в своей окончательной форме; в противном случае выводится изолированная форма.
  • Область действия: только изолированные и конечные формы (вывод в формате 2-символов) генерируются этим этапом обработки. Символы начальных форм, определенных в Unicode, FBF8 (YEH-HAMZA + E) и FBFB (УЙГУРСКИЙ YEH-HAMZA + ALEF MAKSURA), не создаются. Приложениям, которым требуются эти варианты с тремя символами, необходимо использовать цепочные контекстные подстановки GSUB 'rlig' / 'clig' через ApplyContextualSubst. Другие регионы арабских лигатур (Allah U+FDFA / FDFB, декоративные лигатуры в диапазоне FC00-FDC7) требуют управления GSUB 'rlig' / 'dlig' и находятся за пределами области действия статического генератора. PDF-файлы, не содержащие YEH-HAMZA, за которым следует одна из восьми поддерживаемых гласных букв, генерируются идентично версии v2.119.57; новый этап обработки выполняется только для определенных последовательностей из 2 символов.

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 недавно классифицированных букв, 15 букв, соединяющих "D" и состоящих из 4 форм (TTEHEH U+067A → FB5E-FB61, BEEH U+067B → FB52-FB55, TEHEH U+067F → FB62-FB65, BEHEH U+0680 → FB5A-FB5D, NYEH U+0683 → FB76-FB79, DYEH U+0684 → FB72-FB75, TCHEHEH U+0687 → FB7E-FB81, VEH U+06A4 → FB6A-FB6D, PEHEH U+06A6 → FB6E-FB71, NG U+06AD → FBD3-FBD6, NGOEH U+06B1 → FB9A-FB9D, GUEH U+06B3 → FB96-FB99, RNOON U+06BB → FBA0-FBA3, HEH DOACHASHMEE U+06BE → FBAA-FBAD, которая является стандартной буквой "h" в урду, и E U+06D0 → FBE4-FBE7 для казахского/киргизского арабского алфавита), а также 11 букв, соединяющих "R" и состоящих из 2 форм (DAHAL U+068C → FB84-FB85, DDAHAL U+068D → FB82-FB83, DUL U+068E → FB86-FB87, KIRGHIZ OE U+06C5 → FBE0-FBE1, OE U+06C6 → FBD9-FBDA, U U+06C7 → FBD7-FBD8, YU U+06C8 → FBDB-FBDC, KIRGHIZ YU U+06C9 → FBE2-FBE3, VE U+06CB → FBDE-FBDF, YEH BARREE U+06D2 → FBAE-FBAF, которая является окончанием слова "yeh" в урду, и YEH BARREE WITH HAMZA ABOVE U+06D3 → FBB0-FBB1), теперь напрямую отображаются табличным формером без необходимости использования формера GSUB для шрифта.
  • Две буквы, HEH DOACHASHMEE и YEH BARREE, заслуживают особого упоминания, поскольку их слоты Forms-A (FBAA-FBAD и FBAE-FBAF) были ошибочно назначены в версии v2.119.52 для U+06C2 HEH GOAL WITH HAMZA ABOVE и U+06C3 TEH MARBUTA GOAL. В версии v2.119.56 эти неправильные соответствия были устранены, а в версии v2.119.57 слоты были привязаны к правильным исходным буквам, что обеспечило чистоту отслеживания изменений и окончательное разрешение конфликта. Буквы в диапазоне U+0672-U+06D5, не имеющие записей Presentation Forms-A в Unicode 16 (около 50 дополнительных кодовых точек, в основном варианты REH / DAL / SEEN / SAD / TAH / AIN / FEH / QAF / KAF без предварительно закодированных форм), по-прежнему участвуют в анализе классов объединения, чтобы соседние символы формировались правильно; сами буквы передаются как необработанные кодовые точки и полагаются на таблицы GSUB шрифта в движке GSUB v2.119.43-50 для выбора собственной формы. Скомпилировано в 78018 строк; PDF-файлы, не содержащие эти новые кодовые точки, идентичны по байтам версии v2.119.56.

2026-05-22 Version 2.119.56

  • Исправлена ошибка в формировании текста на арабском языке: в версии v2.119.52 были некорректно определены соответствия для двух символов, используемых в регионах Урду/Синди, в отношении арабских вариантов представления (Presentation Forms-A). Символ U+06C2 HEH GOAL WITH HAMZA ABOVE был сопоставлен с FBAA-FBAD, что фактически является диапазоном кодовых точек для U+06BE HEH DOACHASHMEE; программы для чтения отображали глиф "Урду, цель-Хэ с хамзой" как стандартный глиф "Урду, Хэ-Доашашми". Символ U+06C3 TEH MARBUTA GOAL был сопоставлен с FBAE-FBAF, что фактически является диапазоном кодовых точек для U+06D2 YEH BARREE; программы для чтения отображали "Тэ-Марбута-Цель" как слово "Урду, Йэ-Барри". Согласно Unicode 16.0, ни для U+06C2, ни для U+06C3 не предусмотрены предварительно закодированные варианты представления A; оба символа должны передаваться без изменений в виде исходных кодовых точек (программы для чтения отображают их правильно с помощью cmap шрифта и любой обработки форматирования, основанной на GSUB).
  • Исправлены две ошибочные записи в таблице подстановки _ArabicShape Presentation Forms-A, используемой для формирования арабского текста на стороне генератора версии v2.85.0; символы U+06C2 и U+06C3 теперь обрабатываются по пути "прозрачной передачи" и выводятся без изменений. Записи классов соединений из версии v2.119.52 (D для U+06C2, R для U+06C3) сохранены, чтобы соседние символы по-прежнему отображались в правильной позиционной форме, когда эти символы встречаются в слове. Это исправление влияет только на PDF-файлы, содержащие символы U+06C2 или U+06C3 с включенной функцией AutoShapeArabic; PDF-файлы, не содержащие эти два символа, идентичны по байтам выходным файлам версии v2.119.55. В сопутствующей версии v2.119.57 расширена поддержка Forms-A для дополнительных персидских/урду/синдхи/кашмирских/уйгурских/казахских/кыргызских символов, включая символы HEH DOACHASHMEE и YEH BARREE, которые были ошибочно объединены в версии v2.119.52.

2026-05-22 Version 2.119.55

  • Возможности форматирования текста для языка Devanagari: добавлены два новых публичных метода в THotPDF, которые охватывают парадигму форматирования для языков Индии, которая не соответствует механизму определения классов символов, используемому для арабского, сирийского и монгольского языков (v2.85.0 + v2.119.32-54). Метод GetDevanagariCategory (CP) возвращает упрощенную категорию слогов для языка Индии (0 = Другое, 1 = Согласный, 2 = Независимая гласная, 3 = Matra, 4 = Virama, 5 = Nukta, 6 = Bindu, 7 = Visarga, 8 = Danda, 9 = Цифра, 10 = ZWJ, 11 = ZWNJ, 12 = Модификатор) в соответствии с Unicode 16.0 §12.1 + IndicSyllabicCategory.txt; таблица охватывает весь блок Devanagari U+0900-U+097F, включая расширения Marwari, Sindhi и Vedic в диапазоне U+0978-U+097F.
  • Функция `ApplyDevanagariReorder (Wide)` проходит по входной строке слева направо и применяет предварительный этап переупорядочения для каждого слога деванагари, возвращая переупорядоченную строку Unicode, готовую для использования с cmap и GSUB. Не относящийся к деванагари контент (латиница, цифры, знаки препинания, другие скрипты) передается без изменений. Реализованы два варианта переупорядочения (которые наиболее распространены в реальных сценариях форматирования деванагари): (1) Repha — когда слог начинается с Ra (U+0930) + Halant (U+094D) + согласный, пара (Ra, Halant) перемещается в КОНЕЦ слога, чтобы функция GSUB 'rphf' шрифта заменила ее глифом Repha, который визуально прикрепляется к верхнему правому углу слога; (2) Pre-base I-matra — U+093F перемещается в НАЧАЛО слога (после удаления Repha), чтобы процесс GSUB слева направо видел его перед кластером согласных, соответствуя порядку его визуального отображения.
  • Caller pipeline: Применение DevnagariReorder к тексту в логическом порядке -> Установка подстрочного символа 'deva' -> перебор упорядоченных символов с применением правил GSUB ('nukt' / 'akhn' / 'rphf' / 'rkrf' / 'half' / 'vatu' / 'cjct' / 'pres' / 'blws' / 'abvs' / 'psts' / 'haln') с использованием GetSingleSubstituteGlyph + ApplyLigatureSubstitution + ApplyContextualSubst -> вывод полученных идентификаторов глифов в поток текста PDF, одновременно вызывая MarkUnicodeGlyphUsed (GID) для каждого вывода, для подсистемы подмножества v2.84.0. С завершением этапов A (v2.119.52, поддержка Arabic Extended-A), B (v2.119.53, поддержка Syriac), C (v2.119.54, поддержка Mongolian) и D (v2.119.55, поддержка Devanagari Indic), проблема "форматирования текста Mongolian / Syriac / Devanagari" полностью решена. За пределами текущей реализации: скрипты Devanagari Indic, отличные от Devanagari (бенгальский, тамильский, телугу, гуджарати — каждый имеет свои собственные данные и правила упорядочивания), правила упорядочивания, выходящие за рамки Repha + префикс I-matra, и автоматическое форматирование Devanagari на стороне генератора внутри TextOut / BuildUnicode*FieldContent (зарезервировано для этапа 8 дорожной карты движка GSUB).

2026-05-22 Version 2.119.54

  • Возможности форматирования монгольского текста: два новых открытых метода в THotPDF позволяют выполнять поиск по классам объединения монгольского текста (U+1800-U+18AF) и контекстный анализ из 4 позиций, чтобы вызывающие функции могли управлять форматированием монгольского текста на стороне генератора. GetMongolianJoiningClass (CP) возвращает класс объединения монгольского текста в соответствии с Unicode 16.0 §13.5 (0 = не объединяется, 2 = двойное объединение, 4 = прозрачный / символ вариации) для любого символа; таблица охватывает базовый монгольский язык, а также расширения Todo, Sibe, Manchu и Ali Gali (U+1820-U+1878 + U+1887-U+18A8 + ALI GALI DAGALGA U+18A9 + MANCHU ALI GALI LHA U+18AA) и классифицирует NIRUGU (U+180A), три символа вариации FVS1-FVS3 (U+180B-U+180D) и символы гласных Ali Gali BALUDA / THREE BALUDA (U+1885-U+1886) как прозрачные. GetMongolianPosition (Wide, Index) анализирует окружающий текст, игнорируя прозрачные символы, и возвращает 0 = изолированный, 1 = конечный, 2 = начальный или 3 = медиальный для буквы с индексом, отсчитываемым от нуля.
  • Как и для сирийского шрифта (v2.119.53), в монгольском шрифте НЕТ предварительно закодированных форм представления в Unicode — каждый шрифт, поддерживающий монгольский язык (Mongolian Baiti, Noto Sans Mongolian, Noto Serif Mongolian и т.д.), использует позиционное форматирование через OpenType GSUB-таблицы в своих функциях 'init', 'medi', 'fina' и 'isol' под тегом скрипта 'mong'. Таким образом, версия v2.119.54 следует той же модели, что и v2.119.53, ориентированной только на возможности; вызывающие программы формируют выходные данные о позиции, используя API-интерфейсы GSUB (SetGSUBScript ('mong'), GetSingleSubstituteGlyph для соответствующего тега позиционной функции, MarkUnicodeGlyphUsed для подсистемы v2.84.0), чтобы создать форматированные идентификаторы глифов (GIDs), которые непосредственно выводятся в поток текста PDF.
  • В монгольском языке текст пишется вертикально, сверху вниз, в своей родной системе письма; компоновщик работает с логическим порядком кодовых точек (предыдущий/следующий в потоке кодовых точек), независимо от визуальной ориентации. Фактическая отрисовка сверху вниз осуществляется на этапе создания PDF-файла с помощью параметра /WMode 1 (вертикальная запись) или поворота матрицы шрифта, а не компоновщиком. Классификация Free Variation Selectors (FVS) как прозрачных означает, что компоновщик правильно обрабатывает позиционные формы, даже если после буквы следует FVS; таблица подстановки (GSUB) шрифта для функций 'fina', 'medi', 'init' и 'isol' автоматически выбирает вариант, зависящий от FVS, когда FVS встречается во входном потоке. Компоновка Devanagari (индийского письма) остается зарезервированной для будущих версий, поскольку она требует предварительного этапа переупорядочивания в соответствии с UAX #38 (переупорядочивание вирамы/групп согласных/основных элементов), что не соответствует 4-позиционному компоновщику, используемому для арабского/сирийского/монгольского письма. Автоматическая компоновка монгольского языка в функциях TextOut / BuildUnicode*FieldContent остается зарезервированной для 8-й фазы дорожной карты движка GSUB.

2026-05-22 Version 2.119.53

  • Возможности форматирования сирийского текста: два новых открытых метода в THotPDF предоставляют возможность поиска класса объединения для сирийского текста (U+0700-U+074F) и контекстного анализа из 4 позиций, чтобы вызывающие функции могли управлять форматированием сирийского текста на стороне генератора. GetSyriacJoiningClass (CP) возвращает класс объединения SyriacShaping.txt в соответствии со стандартом Unicode 16.0 (0 = U - не объединяется, 1 = R - объединяется справа, 2 = D - объединяется двунаправленно, 4 = T - прозрачный / NSM) для любого символа; таблица охватывает все 35 сирийских букв в базовом блоке, а также расширения персидского и согдийского алфавитов (PERSIAN BHETH / GHAMAL / DHALATH в U+072D-U+072F, SOGDIAN ZHAIN / KHAPH / FE в U+074D-U+074F) и классифицирует SUPERSCRIPT ALAPH (U+0711) и сирийские диакритические знаки (U+0730-U+074A) как прозрачные. GetSyriacPosition (Wide, Index) анализирует окружающий текст, игнорируя прозрачные знаки, и возвращает 0 = изолированный, 1 = конечный, 2 = начальный или 3 = медиальный для буквы, находящейся по индексу (отсчет начинается с 0).
  • В отличие от арабского языка (который имеет предварительно закодированные формы представления B (U+FE70-U+FEFF) и формы A (U+FB50-U+FBFF), которые позволяют HotPDF напрямую переписывать кодовые точки в вариации с формой), в блоке сирийского языка НЕТ предварительно закодированных форм представления в Unicode — каждый шрифт, поддерживающий сирийский язык (Estrangelo Edessa, Serto Jerusalem, East Syriac Adiabene, Noto Sans Syriac и т. д.), использует позиционное форматирование через таблицы подстановки OpenType в своих функциях 'init', 'medi', 'fina' и 'isol'. Поэтому версия v2.119.53 включает только базовый функционал; вызывающий код должен комбинировать выходные данные позиционирования с API движка подстановки GSUB версии v2.119.43-50 (SetGSUBScript ('syrc'), GetSingleSubstituteGlyph для соответствующего тега функции позиционирования, MarkUnicodeGlyphUsed для подсистемы v2.84.0) для создания форматированных идентификаторов глифов (GIDs), которые непосредственно выводятся в поток текста PDF.
  • Область применения терминальной формы символа "Алаф": В Unicode §9.3 описаны две контекстные терминальные особенности ('fin2', применяемая после DALATH / RISH, и 'fin3', применяемая после FINAL LAMADH), которые шрифты сирийского письма используют для замены глифа "Алаф" на конечный. В версии v2.119.53 символ "Алаф" (U+0710) классифицируется как основной символ, объединяющий символы справа, и возвращает только 0 (изолированный) или 1 (конечный); вызывающие процедуры, которым требуется различение 'fin2' / 'fin3', используют цепочные контекстные подстановки шрифта с помощью функции ApplyContextualSubst и соответствующих тегов. Формирование текста для монгольского и деванагари (индийского) языков остается зарезервированным для будущих версий: монгольский язык использует селекторы свободной вариации и гармонию гласных, деванагари требует предварительного этапа переупорядочивания в соответствии с UAX #38, ни один из них не соответствует сирийскому алгоритму обхода с 4 позициями. Автоматическое формирование текста для сирийского письма внутри функций TextOut / BuildUnicode*FieldContent остается зарезервированным для 8-й фазы дорожной карты движка GSUB.

2026-05-22 Version 2.119.52

  • Расширение для форматирования арабского текста: статичный арабский компоновщик, реализованный на стороне производителя в версии v2.85.0, теперь охватывает оставшиеся символы из набора Arabic Extended-A (ALEF WASLA U+0671, NOON GHUNNA U+06BA, варианты HEH U+06C0-U+06C3), блок Arabic Supplement U+0750-U+077F (арабские буквы, используемые в африканских языках, таких как хауса и волоф), и новый регион Arabic Extended-A U+08A0-U+08FF (арабский язык Корана + расширенные буквы хауса/волоф + диакритические знаки для арабского языка Корана). Классы объединения берутся из файла ArabicShaping.txt в Unicode 16.0 и применяются во время анализа позиций в четырех направлениях в версии v2.85.0, чтобы соседние символы выбирали правильную форму init/medi/fina/isol, независимо от того, какой арабский вариант находится рядом с ними.
  • Буквы, имеющие предопределенные статические формы в блоке Arabic Presentation Forms-A (U+FB50-U+FBFF), теперь напрямую отображаются в эти формы без необходимости использования OpenType GSUB: ALEF WASLA -> FB50/FB51 (правое соединение, две формы), NOON GHUNNA -> FB9E/FB9F (двойное соединение в соответствии с Unicode, но только две предопределенные формы; init/medi плавно переходят в isol), HEH WITH YEH ABOVE -> FBA4/FBA5 (правое соединение, две формы), HEH GOAL -> FBA6/FBA7/FBA8/FBA9 (двойное соединение, все четыре формы), HEH GOAL WITH HAMZA ABOVE -> FBAA/FBAB/FBAC/FBAD (двойное соединение, все четыре формы), TEH MARBUTA GOAL -> FBAE/FBAF (правое соединение, две формы). В сочетании с обязательным этапом постобработки лигатуры LAM-ALEF версии v2.119.32 и базовым набором из 9 букв для персидского/урду языка версии v2.119.35, статический шейдер теперь охватывает практически весь современный арабский, персидский, урду, синдхи, пашту, курдский, уйгурский, а также арабский язык, используемый в Коране, и африканский арабский (хауса, волоф и др.), не завися от таблицы GSUB шрифта.
  • Дополнения Arabic Supplement (U+0750-U+077F) и более новая область Arabic Extended-A (U+08A0-U+08C7) не имеют предварительно закодированных статических форм представления; их записи классов объединения позволяют соседним символам формироваться правильно, но сами символы остаются необработанными кодовыми точками и зависят от шрифта, поддерживающего GSUB (или от API движка GSUB v2.119.43-50, управляемого вызывающей стороной), для своей собственной позиционной обработки. Область Arabic Extended-A, содержащая диакритические знаки, используемые в Коране (U+08CA-U+08E1, U+08E3-U+08FF), классифицируется как прозрачная (T-соединение), поэтому анализ позиционирования соседних символов пропускает ее, что соответствует существующей обработке harakat (U+064B-U+065F). Текст, не содержащий эти расширенные символы, остается идентичным по байтам результатам, полученным в версии v2.119.51. Формирование текста на монгольском, сирийском и деванагари (использующие различные модели формирования) остается зарезервированным для будущих версий.

2026-05-22 Version 2.119.51

  • Поддержка контейнеров XFA (XML Forms Architecture) на стороне генератора: в соответствии с PDF 1.7 §12.7.6 + §12.7.8, объект AcroForm может содержать запись /XFA наряду с (или вместо) статического массива /Fields. Новый метод THotPDF.AddXFAPacket(PacketName, XMLBytes) регистрирует пакет XFA с указанным именем. Типичные имена пакетов: 'template' (макет формы + скрипты), 'datasets' (привязка данных), 'config' (конфигурация просмотра), 'connectionSet', 'localeSet', 'stylesheet', 'xfdf', 'xmpmeta', 'signature' и 'sourceSet'. Каждый зарегистрированный пакет становится одним сжатым потоком FlateDecode в конце документа, а массив /XFA чередует строки с именами пакетов и ссылки на потоки в порядке регистрации, что обеспечивает детерминированную последовательность байтов для макета. Методы THotPDF.ClearXFAPackets и THotPDF.XFAPacketCount дополняют интерфейс API.
  • Поддержка реализована только на уровне контейнера — HotPDF не анализирует XML XFA, не реализует механизм динамической компоновки XFA, не выполняет код FormCalc или JavaScript внутри шаблона XFA и не проверяет структуру шаблона. Приложение само создает XML XFA (обычно с помощью Adobe LiveCycle Designer или вручную, следуя спецификации XFA 3.3), а HotPDF выводит байты без изменений. Приложения, использующие движок XFA (более старые версии Acrobat/Reader, FormsCentral, некоторые киоски), отображают форму; приложения без движка XFA (Adobe Reader DC, начиная с 2017 года, большинство приложений с открытым исходным кодом) отображают поля AcroForm в качестве резервного варианта, если документ является гибридным документом, сочетающим AcroForm и XFA.
  • PDF/A и PDF/X: Соответствие стандартам ISO 19005-1 §6.4.2 / ISO 19005-2 §6.4.2 / ISO 19005-3 §6.4.2 явно запрещает использование форм XFA (движок динамической компоновки не может быть надежно архивирован). Рабочие процессы предварительной обработки ISO 15930 полностью отвергают интерактивные формы. Функция AddXFAPacket немедленно выдает ошибку, если параметры PDFACompliance или PDFXCompliance не пустые, при этом указывается соответствующая ссылка на спецификацию. Обнаружение дублирующихся имен пакетов приводит к ошибке. Пустое имя пакета или пустой XMLBytes также приводят к ошибке. Функция RequirePDFVersion (pdf15) автоматически увеличивает версию документа. Словарь AcroForm теперь генерируется, если в нем есть хотя бы одна запись в разделе "/Fields" ИЛИ зарегистрирован хотя бы один пакет XFA; в версиях до v2.119.51, если пакеты не регистрируются, вывод словаря /AcroForm остается идентичным по размеру.

2026-05-22 Version 2.119.50

  • TTF-компилятор для символов замены GSUB: новый метод THotPDF.MarkUnicodeGlyphUsed (GID: Word) добавляет символ в набор символов для подмножества в версии v2.84.0, независимо от того, содержит ли таблица cmap соответствующий кодовый пункт. В версии v2.84.0 набор использованных символов определяется из FUnicodeUsedCps через таблицу cmap, поэтому все символы замены, добавленные GSUB (стилистические альтернативы, лигатуры, контекстные варианты, весь вывод API запросов Phase 1-6), ранее были невидимы для компилятора подмножества, и потребительский ридер отображал вместо них символ .notdef. Теперь, после вывода любого GID, возвращенного функциями GetSingleSubstituteGlyph / GetMultipleSubstituteGlyphs / GetAlternateGlyph / ApplyLigatureSubstitution / ApplyContextualSubst / ApplyReverseChainedContextualSubst в поток текста PDF, вызывающий код вызывает MarkUnicodeGlyphUsed (GID) один раз для каждого выведенного GID, чтобы добавить его в встроенный набор символов.
  • Этот компонент является идемпотентным (повторные вызовы с одним и тем же GID не приводят к изменению), устойчивым к ошибкам (GID, превышающий FUnicodeNumGlyphs, игнорируется, вызовы, выполненные до вызова RegisterUnicodeTTF, не имеют эффекта), и интегрируется с этапом v2.84.0 обработки составных глифов в _BuildSubsetTTF. Вызывающему коду необходимо только указать GID верхнего уровня; составные компоненты автоматически извлекаются существующим механизмом _TTFWalkCompositeClosure. Набор выделяется лениво при первом вызове и сбрасывается в пустое состояние при каждом вызове RegisterUnicodeTTF ('', nil) вместе с остальным состоянием подмножества. Благодаря реализации этапа 9, каждый запрос API GSUB этапов 1-7 можно безопасно использовать вместе с генерацией подмножества, не опасаясь, что замененные глифы исчезнут из встроенного шрифта.

2026-05-22 Version 2.119.49

  • OpenType GSUB Script / LangSys selection API: пять новых публичных методов в THotPDF позволяют вызывающим кодам привязать таблицы GSUB к определенному сценарию и языку, а не к историческому сценарию DFLT и языковой системе по умолчанию. `SetGSUBScript ('latn' / 'arab' / 'cyrl' / 'hani' / 'kana' / 'deva' / 'beng' / 'taml' / и т.д.)` выбирает тег сценария OpenType; пустая строка по умолчанию сохраняет базовую линию v2.119.43-48 (предпочтительно 'DFLT', в противном случае используется первый сценарий). `SetGSUBLanguage ('ENG ' / 'TUR ' / 'AZE ' / 'JAN ' / 'KOR ' / 'ARA ' / и т.д., с добавлением пробела в конце для заполнения 4 байт)` выбирает тег языка OpenType; пустая строка соответствует языковой системе по умолчанию для сценария. Обе настройки сохраняются между запросами GSUB и сбрасываются в пустую строку при вызове `RegisterUnicodeTTF ('', nil)`.
  • Три новых вспомогательных функции позволяют узнать, какие возможности шрифта загружены: `GetGSUBScripts`: `TGSUBStringArray` возвращает все теги скриптов в порядке, указанном в `ScriptList`; `GetGSUBLanguages(ScriptTag)` возвращает все теги языков, доступные для заданного скрипта (с заполнителем '' в индексе 0, если для скрипта определен язык по умолчанию); `GetGSUBFeatures(ScriptTag, LangTag)` возвращает все теги функций (например, 'liga', 'salt', 'aalt', 'ss01' - 'ss20'), объявленные для определенной комбинации (скрипт, язык) в порядке, указанном в `featureIndices` для `LangSys`. Если `ScriptTag` или `LangTag` не указаны, используются те же механизмы отладки, что и для API замены, поэтому вызывающий код может использовать `GetGSUBFeatures('', '')` для перечисления функций, определенных для пути по умолчанию, без предварительного просмотра списка скриптов.
  • Строгие правила выбора с возможностью отката: когда SetGSUBScript устанавливается в тег, который загруженный шрифт не рекламирует, последующие запросы GSUB возвращают пустые результаты или не выполняются — движок НЕ переключается автоматически на DFLT, поэтому вызывающий код может четко определить, что выбранный скрипт недоступен. Когда SetGSUBLanguage устанавливается в нераспознанный тег, он, как и рекомендуется в спецификации OpenType, переключается на язык по умолчанию для этого скрипта. Семь существующих методов подстановки GSUB (GetSingleSubstituteGlyph / GetMultipleSubstituteGlyphs / GetAlternateGlyphCount / GetAlternateGlyph / ApplyLigatureSubstitution / ApplyContextualSubst / ApplyReverseChainedContextualSubst) сохраняют свои публичные сигнатуры без изменений; только внутренний помощник _GSUBFindFeatureLookups получает два дополнительных параметра, которые теперь передаются во все семь мест вызова. С внедрением API Script / LangSys и матрицы LookupType 1-8, движок GSUB полностью готов к использованию только для определения возможностей; оставшиеся этапы дорожной карты (автоматическая система форматирования + усечение TTF) направлены на интеграцию на стороне производителя, а не на создание новых возможностей запросов.

2026-05-22 Version 2.119.48

  • OpenType GSUB Reverse Chained Contextual Single Substitution (LookupType 8): новый метод THotPDF.ApplyReverseChainedContextualSubst (const InputGIDs; StartIndex; FeatureTag; out OutGID): Boolean является последним типом GSUB lookup, который был реализован. LookupType 8 выполняет контекстно-зависимую одно-к-одному замену, при которой заменяемый глиф выбирается на основе индекса Coverage входного глифа, и его отличительной особенностью является то, что вызывающий код должен применять его в ОБРАТНОМ порядке сканирования по последовательности нескольких глифов (от конца к началу), поскольку каждая замена может зависеть от контекста БУДУЩЕГО просмотра, который еще не был заменен. Этот вспомогательный метод является одноточечным, и вызывающий код управляет циклом обратного сканирования. Поддерживаются форматы Coverage 1 и 2, флаги Lookup, учитывающие входные данные, откат и просмотр вперед, а также расширения (LookupType 7).
  • Типичный сценарий использования: определенные арабские/сирийские/N'Ko/индийские контекстные альтернативные глифы, окончательная форма которых зависит от формы следующего глифа. Некоторые шрифты также используют это для разрешения неоднозначности последовательностей латинских символов. В отличие от LookupType 5/6, Type 8 не имеет встроенных механизмов вложенных подстановок, поскольку замена является однозначной (1:1). Если нет совпадения, возвращается False, OutGID = InputGIDs[StartIndex] (попытка соответствия контракту GetSingleSubstituteGlyph версии v2.119.43).
  • Закрывает матрицу LookupType: начиная с версии v2.119.48, для каждого типа LookupType GSUB в OpenType (от 1 до 8) существует отдельная общедоступная функция в THotPDF. API выбора скрипта/языковой системы, автоматическая интеграция конвейера форматирования и автоматическая загрузка заменяемых глифов из TTF остаются зарезервированными для этапов 7-9; вызывающие программы по-прежнему должны самостоятельно отмечать выбранные заменяемые глифы в подмножестве встроенного шрифта и управлять циклом обратного сканирования.

2026-05-22 Version 2.119.47

  • OpenType GSUB: контекстная и цепочная контекстная подстановка (LookupType 5 + 6): новый метод THotPDF.ApplyContextualSubst (const InputGIDs; StartIndex; FeatureTag; var OutGIDs; out ConsumedLen): Boolean является единой точкой входа, охватывающей LookupType 5 (только контекст ввода) и LookupType 6 (возврат, контекст ввода/предпросмотра) для всех трех форматов подтаблиц: формат 1 (последовательности идентификаторов глифов), формат 2 (последовательности классов ClassDef) и формат 3 (последовательности таблиц Coverage, каноническая форма, используемая в большинстве современных шрифтов). Канонические пользователи включают 'rclt' (требуемые контекстные альтернативы — арабские позиционные формы init/medi/fina/isol, когда шрифт использует их через GSUB), 'clig' (контекстные лигатуры), 'calt' (контекстные альтернативы) и функции формовки для индийских шрифтов 'pres' / 'blws' / 'psts' / 'half' / 'pstf' / 'cjct'.
  • Вложенный диспетчер поиска SequenceLookupRecord: когда применяется контекстное правило, каждая запись SequenceLookupRecord запускает вложенный поиск в определенной позиции внутри соответствующей подпоследовательности входных данных. Новый вспомогательный класс _GSUBApplyNestedLookup повторно входит в список GSUB LookupList, прозрачно обрабатывает обертки Extension и направляет запросы к однократным (Type 1) / множественным (Type 2) / альтернативным (Type 3, первый вариант) / лигатурным (Type 4) обработчикам. Диспетчер отслеживает индексы массива MatchPositions[], чтобы последующие записи SequenceLookupRecord продолжали обращаться к правильным позициям, даже когда множественная замена расширяет 1→N или лигатурная замена объединяет N→1 глифы вокруг них. Вложенные типы поиска 5 / 6 / 8 (рекурсивные контекстные) намеренно отложены; в большинстве реальных шрифтов вложенные поиски настроены на типы 1 / 4.
  • При совпадении метод возвращает True вместе с последовательностью глифов, которые должны заменить InputGIDs[StartIndex..StartIndex+ConsumedLen-1]. Длина OutGIDs может отличаться от ConsumedLen, когда выполняются вложенные операции поиска 1→N или N→1. ConsumedLen всегда представляет собой общий диапазон входных данных, который охватывает контекстное правило (включая символы, пропущенные флагом LookupFlag, между значимыми глифами); типичный вызывающий код цикла сканирования продвигается на ConsumedLen и выдает OutGIDs. Если совпадение не найдено, возвращается False, пустой OutGIDs и ConsumedLen = 1 — это тот же безопасный контракт бездействия, что и в вспомогательных функциях v2.119.43-46. Флаг LookupFlag (фаза 4) применяется на протяжении всего контекстного сопоставления: операции отката, ввода и предварительного просмотра обрабатывают все глифы, помеченные для игнорирования. Скрипт / LangSys остаются зафиксированными на значении DFLT по умолчанию для этого фрагмента; выбор API находится в области действия фазы 7.

2026-05-22 Version 2.119.46

  • OpenType GSUB Extension Lookups (LookupType 7): движок GSUB теперь прозрачно распаковывает расширенные таблицы подстановок — это чистый уровень косвенной адресации, который спецификация OpenType определяет для шрифтов, у которых фактическая таблица подстановок находится за пределами 16-битного диапазона смещения LookupList. Каждый публичный API версии v2.119.43-45 (GetSingleSubstituteGlyph / GetMultipleSubstituteGlyphs / GetAlternateGlyphCount / GetAlternateGlyph / ApplyLigatureSubstitution) автоматически использует 32-битное косвенное указание Offset32 для доступа к фактическим подтаблицам LookupType 1 / 2 / 3 / 4. Это изменение структуры данных позволяет использовать большие шрифты CJK / Indic OpenType (Noto Sans CJK, Noto Sans Devanagari и т.д.), таблицы GSUB которых превышают 64 КБ, и которые ранее использовали LookupType 7 для хранения своих таблиц подстановок; ранее такие шрифты выглядели так, будто не содержат никаких функций, в HotPDF.
  • Обработка таблицы OpenType GDEF (определение глифов): функция RegisterUnicodeTTF теперь также кэширует таблицу GDEF шрифта, если она присутствует. Три подтаблицы GDEF управляют логикой обработки флагов Lookup: GlyphClassDef классифицирует каждый GID как базовый (1) / лигатура (2) / диакритический знак (3) / компонент (4); MarkAttachClassDef присваивает каждому глифу диакритического знака класс присоединения; MarkGlyphSetsDef (v1.2+) определяет именованные наборы глифов диакритических знаков. Реализованы оба формата ClassDef: формат 1 (startGlyphID + classValueArray) и формат 2 (отсортированные записи classRangeRecords); принимаются все заголовки GDEF v1.0 / v1.1 / v1.2 (элемент itemVariationStore в v1.3 игнорируется). Для шрифтов, не имеющих таблицы GDEF, используется поведение по умолчанию v2.119.43-45 ("ни один глиф не игнорируется"), чтобы сохранить идентичный выходной файл для вызывающих программ, использующих шрифты, в которых отсутствует GDEF.
  • OpenType GSUB LookupFlag: все пять общедоступных API GSUB теперь считывают флаг LookupFlag каждой таблицы Lookup (и необязательный дополнительный uint16, представляющий набор фильтров для меток, если установлен флаг LookupFlag.useMarkFilteringSet) и пропускают входные глифы, помеченные как игнорируемые. Определенные в спецификации биты флагов учитываются: 0x0002 ignoreBaseGlyphs (пропускает класс 1 GDEF.GlyphClassDef), 0x0004 ignoreLigatures (пропускает класс 2), 0x0008 ignoreMarks (пропускает класс 3), 0x0010 useMarkFilteringSet (только метки, входящие в указанный MarkGlyphSet, участвуют), и старший байт markAttachmentType (участвуют только метки, соответствующие запрошенному MarkAttachClassDef). Для замены лигатур (LookupType 4) это наиболее важно: лигатуры 'rlig' арабского языка / 'akhn' индийских языков, компоненты которых разделены метками (например, LAM + Fatha + ALEF), теперь правильно сопоставляются при установке флага LookupFlag.ignoreMarks, и возвращаемое значение ConsumedCount включает пропущенные метки, поэтому цикл сканирования вызывающей стороны переходит к каждому поглощенному входному глифу. Бит 0x0001 (rightToLeft) является специфичным для GPOS и остается игнорируемым для поисков GSUB.
  • Текущие меры безопасности по-прежнему применяются: шрифты без таблицы GSUB, вызывающие, передающие тег, отличный от 4-байтного, функции, которые шрифт не рекламирует как поддерживаемые, GID, для которых нет подтаблицы, и теперь входные глифы, игнорируемые флагом LookupFlag, все возвращают безопасный результат "no-op" версии v2.119.43-45. Пять публичных API сохраняют стабильность байтов; только внутренний процесс поиска использует расширение, учитывает флаг LookupFlag и классификацию GDEF. API выбора сценария/языковой системы, автоматическая интеграция конвейера форматирования и автоматическое извлечение глифов-заменителей из TTF остаются зарезервированными для будущих версий.

2026-05-22 Version 2.119.45

  • OpenType GSUB замена лигатур (LookupType 4): новый метод THotPDF.ApplyLigatureSubstitution (const InputGIDs: массив идентификаторов глифов; StartIndex; FeatureTag; out OutGID; out ConsumedCount): Boolean объединяет последовательность нескольких глифов в один глиф лигатуры. Наиболее распространенные варианты использования – 'liga' (стандартные лигатуры – fi / fl / ffi / ffl), 'clig' (контекстные лигатуры), 'dlig' (дискреционные лигатуры), 'hlig' (исторические лигатуры), 'rlig' (обязательные лигатуры – арабская LAM-ALEF и аналогичные, когда шрифт формирует текст с помощью GSUB), а также лигатурные функции для индийских шрифтов ('akhn', 'pres', 'blws', 'psts'). Вызывающая сторона передает последовательность идентификаторов глифов, полученных после обработки cmap, и начальную позицию (отсчет с нуля); при полном совпадении вспомогательный метод возвращает True, OutGID = идентификатор глифа-заменителя лигатуры, а ConsumedCount = общее количество использованных компонентов (обычно >= 2). Если совпадение не найдено, возвращается False, OutGID = 0, ConsumedCount = 1, чтобы вызывающая сторона могла продвинуться на один шаг и продолжить сканирование. Реализация соответствует соглашению OpenType, согласно которому записи в LigatureSet обычно перечисляются в порядке от самого длинного к самому короткому, что позволяет шрифтам с перекрывающимися префиксами (например, лигатуре 'ffi' из трех компонентов и лигатуре 'ff' из двух компонентов) находить более длинное совпадение. Та же защитная логика, что и у вспомогательных методов v2.119.43/.44: пустой или не 4-байтный тег, отсутствие GSUB, отсутствие рекламы функции, StartIndex вне диапазона, а также отсутствие соответствующей подтаблицы LookupType 4 в указанной позиции – все это приводит к безопасному действию без изменений (False / OutGID = 0 / ConsumedCount = 1). Функции LookupFlag для пропуска маркеров, интеграция GDEF GlyphClassDef, автоматическое применение при формировании текста и автоматическое извлечение глифов лигатур из TTF остаются зарезервированными для будущих версий.

2026-05-22 Version 2.119.44

  • OpenType GSUB множественная подстановка (LookupType 2): новый метод THotPDF.GetMultipleSubstituteGlyphs (InputGID, FeatureTag, var OutGIDs) возвращает один входной глиф в виде последовательности глифов-заменителей. Основным пользователем является функция Glyph Composition / Decomposition 'ccmp', которая разделяет предварительно составленные латинские буквы с диакритическими знаками на базовый глиф и диакритические знаки для последующего позиционирования. Этот метод проходит тот же путь DFLT script / default LangSys / FeatureList / LookupList, что и GetSingleSubstituteGlyph версии v2.119.43, и применяет каждую подтаблицу LookupType 2, связанную с запрошенной функцией, к InputGID; первое совпадение имеет приоритет. Массив OutGIDs сбрасывается при входе, чтобы вызывающие функции не должны предварительно очищать его. Пустая последовательность (glyphCount = 0, удаление глифа в соответствии с Unicode), которая разрешена спецификацией, возвращается как Result = True с Length(OutGIDs) = 0, чтобы вызывающая функция могла удалить входной глиф из последовательности.
  • OpenType GSUB: альтернативная подстановка (LookupType 3): два новых метода позволяют получить доступ ко всем альтернативным глифам для стилистических особенностей. `THotPDF.GetAlternateGlyphCount(InputGID, FeatureTag)` возвращает количество альтернативных форм, которые шрифт предлагает для `InputGID` в рамках `FeatureTag`, а `THotPDF.GetAlternateGlyph(InputGID, FeatureTag, AlternateIndex)` возвращает альтернативный глиф по запрошенному индексу, начиная с 0. Наиболее распространенные варианты использования – 'aalt' (Access All Alternates), 'salt' (Stylistic Alternates), 'titl' (Titling Alternates) и 'ss01'–'ss20' (Stylistic Sets 1–20), которые теперь работают с LookupType 3 вместо LookupType 1; в версии v2.119.43 функция `GetSingleSubstituteGlyph` игнорировала эти таблицы подстановки, поэтому ранее пользователи 'aalt' видели только транзитивные замены LookupType 1. Эти функции позволяют пользователям перебирать декоративные глифы (различные формы 'a', 'g', '7'), варианты заглавных букв и альтернативные варианты стилистических наборов. Если `AlternateIndex` выходит за пределы допустимого диапазона или является отрицательным, функция возвращает `InputGID` без изменений, что позволяет пользователям безопасно проверять доступные варианты.
  • Оба вспомогательных модуля соблюдают те же защитные правила, что и версия v2.119.43: шрифты без таблицы GSUB, вызывающие, передающие тег, отличный от 4-байтного, функции, которые шрифт не рекламирует в своем сценарии DFLT, и GID, для которых подтаблица LookupType 2/3 не охватывает все, возвращают безопасный "no-op" (False + пустой OutGIDs для Multiple; 0 / InputGID для Alternate). Подтаблицы LookupType 1/4-8, обнаруженные в цепочке поиска функции, игнорируются в этом фрагменте. Такие функции, как фильтрация LookupFlag, интеграция GDEF GlyphClassDef, API выбора сценария/языковой системы, автоматическая интеграция конвейера форматирования и автоматическое извлечение выбранных глифов подсистемой TTF, остаются зарезервированными для будущих версий; вызывающие функции по-прежнему должны отмечать выбранные глифы в подмножестве встроенного шрифта.

2026-05-22 Version 2.119.43

  • OpenType GSUB: новый механизм поиска стилистических альтернатив THotPDF.GetSingleSubstituteGlyph (InputGID, FeatureTag) проходит по цепочке списков сценариев/списков функций/списков таблиц GSUB шрифта, используя язык и систему по умолчанию сценария DFLT, и применяет каждую подтаблицу LookupType 1 (одиночная замена), связанную с запрошенной функцией, возвращая идентификатор замененного глифа. Наиболее распространенные теги функций стилистических альтернатив: 'salt' (стилистические альтернативы), 'ss01'–'ss20' (наборы стилей 1–20), 'aalt' (доступ ко всем альтернативам), 'titl' (альтернативы для заголовков), 'subs'/'sups' (нижние/верхние индексы), 'frac' (дроби) и 'ordn' (порядковые числа); поддерживаются все 4-байтные теги функций OpenType, цепочка которых содержит подтаблицы LookupType 1. Поддерживаются оба формата Coverage: формат 1 (отсортированный массив глифов, поиск по двоичному дереву) и формат 2 (записи диапазонов). Реализованы оба формата однократной замены: формат 1 (дельта) и формат 2 (массив замен). Теперь RegisterUnicodeTTF кэширует смещение/длину таблицы GSUB вместе с таблицей cmap, чтобы избежать повторного сканирования каталога таблицы при запросе GSUB. Если в шрифте отсутствует таблица GSUB, если вызывающий код передает 4-байтовый тег, который сценарий DFLT шрифта не рекламирует, или если GID отсутствует в области поиска, InputGID возвращается без изменений, что делает API безопасным для использования в качестве функции замены или пропуска. Подтаблицы LookupType 2–8, встречающиеся в цепочке поиска функции, игнорируются в этом первом этапе; множественные замены, альтернативные замены, лигатуры и интеграция автоматической формовки зарезервированы для будущих версий.

2026-05-22 Version 2.119.42

  • AcroForm /DR Resources теперь поддерживает несколько шрифтов Unicode. В версии v2.56.0 функция SetFormUnicodeFontDict отслеживает только один шрифт, предоставленный вызывающим кодом, который становится шрифтом по умолчанию для AcroForm /DA; многоязычные формы, требующие различных систем письма для каждого поля (например, арабский + CJK + латинский в одном PDF), должны были вручную создавать словарь /DR /Font. Новая функция THotPDF.RegisterAcroFormFont (LogicalName, FontDict) регистрирует дополнительный шрифт Unicode под любым логическим именем, делает его доступным для строк /DA для каждого поля (/ 12 Tf) и добавляет его в словарь /DR /Font в AcroForm вместе со шрифтом по умолчанию версии v2.56.0. Порядок регистрации сохраняется, поэтому создаваемый /DR является детерминированным. Конфликты имен с шрифтом по умолчанию SetFormUnicodeFontDict или ранее зарегистрированным шрифтом приводят к ошибке с указанным именем. Пустое LogicalName или nil FontDict также вызывают ошибку. Теперь путь SetFormUnicodeFontDict ('', nil) также очищает реестр дополнительных шрифтов, чтобы начать новый процесс работы с Unicode в известном, чистом состоянии. Допускается во всех уровнях PDF/A / PDF/X — составные шрифты Unicode являются частью метаданных структуры формы, а не интерактивного скрипта.

2026-05-22 Version 2.119.41

  • Перечисление стандартных типов структур, охватывающее таблицу 333 раздела 14.8.4 спецификации PDF 1.7: новое перечисление THPDFStandardStructureType содержит около 40 ролей структуры, определенных в спецификации, и сгруппированных по их роли в PDF (Группировка: 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 + Warichu: Ruby / RB / RT / RP / Warichu / WT / WP; Иллюстрация: Figure / Formula / Form). Два вспомогательных средства на уровне единиц преобразуют перечисление в точные имена, определенные в спецификации PDF: StandardStructureTypeToName (T) возвращает имя, чувствительное к регистру, которое используется в качестве ключа /S элемента структуры, а IsStandardStructureType (Name) проверяет произвольную строку AnsiString на соответствие стандартному набору, чтобы вызывающие процедуры могли предварительно проверять собственные имена ролей и направлять их через AddStructRoleMap, когда это необходимо. Новая перегрузка перечисления AddStructureElement принимает THPDFStandardStructureType напрямую, устраняя риск опечаток и проблем с чувствительностью к регистру ("Para" против "P", "Lbody" против "LBody") в перегрузках с открытой строкой, при этом вызывается та же базовая реализация. Существующие перегрузки, основанные на строках AnsiString, остаются байтово идентичными для вызывающих процедур, использующих собственные или маршрутизированные имена RoleMap.

2026-05-22 Version 2.119.40

  • Установки атрибутов элементов структуры: три новых вспомогательных функции заполняют атрибуты текстовых строк PDF для каждого элемента, которые соответствуют v2.88.0 /Alt + /ActualText и v2.95.0 /ID. THotPDF.SetStructureElementLanguage (Elem, BCP-47 Lang) записывает PDF 1.7 §14.9.2 /Lang, перезаписывая язык по умолчанию для документа для содержимого, находящегося под этим элементом, пока не будет применено другое переопределение /Lang. Типичное использование — это цитируемые отрывки на другом языке или разделы с контентом, использующим разные системы письма. THotPDF.SetStructureElementExpansionText (Elem, ExpansionText) записывает §14.9.5 /E, расшифровку аббревиатур, которую читают программы экранного доступа вместо аббревиатур (например, 'NASA' → 'National Aeronautics and Space Administration'), а также значение, извлеченное при извлечении контента. THotPDF.SetStructureElementTitle (Elem, Title) записывает §14.7.5.2 /T, удобочитаемое название, которое отличает элемент от других элементов с той же ролью в дереве структуры (панель "Теги" в Acrobat отображает /T рядом с именем роли). Все три являются простыми функциями установки, которые не выполняют никаких действий, если значение пустое, вызывают ошибку, если Elem равен nil, и разрешены на всех уровнях PDF/A и PDF/X, поскольку ключи являются структурными метаданными.

2026-05-22 Version 2.119.39

  • Завершены работы по реализации семейства триггеров для полей форм AcroForm: три новых компонента добавлены к AttachFieldKeyStrokeAction (v2.119.37) для закрытия раздела PDF 1.7 §12.7.5.3, таблица 246. THotPDF.AttachFieldFormatAction устанавливает /AA /F (событие форматирования, срабатывает, когда требуется переформатировать отображаемое значение поля после сохранения — типичное использование: применение масок валюты, даты или разделителей тысяч с помощью AFNumber_Format / AFDate_FormatEx). THotPDF.AttachFieldValidateAction устанавливает /AA /V (событие проверки, срабатывает после того, как пользователь вводит новое значение — типичное использование: проверка диапазона или проверка с помощью регулярных выражений с помощью event.rc := false). THotPDF.AttachFieldCalculateAction устанавливает /AA /C (событие вычисления, срабатывает при изменении любого зависимого поля в соответствии с порядком вычислений /Catalog /AcroForm /CO — типичное использование: суммирование или расчет налогов). Все четыре компонента используют один и тот же поиск FFormFields /T, семантику замены, где последнее вызов имеет приоритет, и защиту JavaScript для PDF/A + PDF/X. Другие ключи триггеров в том же словаре /AA (/E /X /D /U /Fo /Bl для триггеров аннотаций и трех связанных триггеров для полей форм) остаются неизменными. Внутренняя реорганизация: AttachFieldKeyStrokeAction теперь делегирует работу общему компоненту _InstallFieldTriggerJSAction; существующие клиенты v2.119.37 увидят идентичные сообщения об ошибках.

2026-05-22 Version 2.119.38

  • RegisterUnicodeTTF теперь сохраняет соответствия между кодовыми точками расширенной многоязыковой плоскости (SMP, U+10000-U+10FFFF) и глифами из таблицы cmap формата 12 загруженного шрифта. В предыдущих версиях записи SMP игнорировались, поскольку массив для поиска соответствия между кодовой точкой и глифом имел размер, соответствующий основной многоязыковой плоскости (BMP). В версии v2.119.38 добавлен параллельный разреженный список (FUnicodeCpToGidSMP), который заполняется вместе с массивом BMP. Новый публичный метод GetUnicodeGlyphForCodepoint(Cp) возвращает идентификатор глифа для любого символа Unicode до U+10FFFF (выполняет двоичный поиск в списке SMP для символов, находящихся выше BMP), или 0 (.notdef), если символ не отображается в таблице cmap загруженного шрифта. Это функциональность, доступная только в этой версии: конвейер шестнадцатеричного кодирования на стороне производителя, поток /CIDToGIDMap и таблица CMap ToUnicode по-прежнему ориентированы на BMP, поэтому для записи символа SMP в поток текста PDF вызывающему коду по-прежнему необходимо самостоятельно генерировать пары суррогатов UTF-16BE. Полная поддержка суррогатов при генерации потока текста зарезервирована для будущей версии. Шрифты, поддерживающие только формат 4, получают пустой список SMP, как и ожидалось.

2026-05-22 Version 2.119.37

  • Добавлен новый помощник для обработки нажатий клавиш в формах AcroForm: `THotPDF.AttachFieldKeyStrokeAction(FieldName, JavaScriptBody)` находит указанный элемент формы по его значению `/T` и устанавливает действие `/AA /K` для выполнения JavaScript-кода при каждом нажатии клавиши во время ввода текста. Это позволяет реализовать такие функции, как проверка ввода в реальном времени (числовые значения, даты, регулярные выражения), маскировка ввода и автоматическое обновление полей, основанное на изменениях в других полях. Этот помощник является идемпотентным: повторные вызовы заменяют запись `/K`, сохраняя при этом любые другие существующие ключи триггера (`/F` для форматирования, `/V` для проверки, `/C` для пересчета, `/Bl` для размытия, `/Fo` для фокусировки и т.д.) в словаре `/AA`. Все уровни PDF/A (ISO 19005-1 §6.6.1, -2/-3 §6.5.1) и все уровни PDF/X (ISO 15930 для подготовки к печати) запрещают действия JavaScript, поэтому помощник немедленно выдает ошибку со ссылкой на соответствующий стандарт, если любой из этих флагов соответствия установлен. Функция основана на словаре событий триггера PDF 1.7 §12.6.3 и таблице 246 для ключа поля формы `/K` (§12.7.5.3).

2026-05-22 Version 2.119.36

  • Теперь функция BeginTaggedContent принимает четыре необязательных свойства последовательности помеченного контента, определенных в PDF 1.7 §14.8.4, таблица 322 (Lang / Alt / ActualText / ExpansionText), и выводит их в виде единого встроенного словаря свойств BDC вместе с существующей записью MCID. Lang содержит тег естественного языка BCP-47 для данного фрагмента (используется программами чтения с экрана и для извлечения текста с учетом языка); Alt – это альтернативное описание для нетекстовых или декоративных фрагментов; ActualText – это текст, используемый для извлечения содержимого и вставки вместо последовательности видимых глифов (важно для лигатур и стилизованных глифов, где видимый символ отличается от базового семантического текста); ExpansionText содержит ключ /E, который расшифровывает аббревиатуры. Пустые параметры пропускают соответствующую запись, поэтому встроенный словарь содержит только те ключи, которые вызывающий код явно заполняет, и старый путь вызова с двумя аргументами остается идентичным по байтам с версией v2.119.35. Экранирование строковых литералов PDF (скобки и обратная косая черта) происходит автоматически; для не-ASCII данных (например, ActualText на китайском, японском, корейском языках, Alt на индийских языках) вызывающий код должен предварительно закодировать свои байты как UTF-16BE с BOM U+FEFF и поместить результат в аргумент AnsiString. Соответствующий API низкого уровня для работы со страницами, BeginMarkedContentMCIDProps, также предоставляется для вызывающего кода, которому требуется прямой контроль над BDC без использования структуры StructElem верхнего уровня.

2026-05-22 Version 2.119.35

  • В ядре Arabic Extended-A, подмножество из 9 персидских/урду символов, теперь используется в четырехпозиционном формирователе на стороне производителя в версии v2.85.0. При включенной функции AutoShapeArabic, следующие символы сопоставляются с соответствующими глифами Arabic Presentation Forms-A (U+FB50-U+FBFF) на основе того же алгоритма контекстного соединения, который используется для основного блока Arabic: PEH U+067E, TCHEH U+0686, JEH U+0698, KEHEH U+06A9, GAF U+06AF, FARSI YEH U+06CC (основной персидский символ), а также TTEH U+0679, DDAL U+0688, RREH U+0691 (основной урду ретрофлексный символ). Символы с двойным соединением отображают полный набор изолированных/конечных/начальных/медийных символов; символы, соединяющиеся только справа (JEH / DDAL / RREH), отображают только изолированные/конечные символы, как и в модели форматирования Arabic. Другие символы Arabic Extended-A (ALEF WASLA U+0671, NOON GHUNNA U+06BA, варианты HEH U+06C0-U+06C3, полный дополнительный блок Arabic U+0750-U+077F) остаются без изменений и будут реализованы в будущей версии. Текст на арабском языке, не относящийся к персидскому/урду, остается идентичным по байтам версии v2.119.34.

2026-05-22 Version 2.119.34

  • Теперь обработка имен в PDF-файлах декодирует последовательности экранирования ISO 32000-1 #XX при импорте или копировании объектов PDF. Имена ресурсов, имена цветов, имена ролей структуры и другие объекты имен, такие как /PANTONE#20216#20CVC, теперь проходят через HotPDF, сохраняя свои исходные байтовые значения, вместо того чтобы быть скопированными обратно с двойным экранированием символа "#".

2026-05-22 Version 2.119.33

  • Обработка дат в PDF теперь более точно соответствует правилам строк дат, определенным в ISO 32000-1. Информация о документе, даты, полученные из XMP, и временные метки подписи используют значение `TDateTime`, предоставленное вызывающей стороной, вместо того, чтобы автоматически заменять его текущим временем. При этом парсер принимает стандартные необязательные поля дат и суффиксы часовых поясов, не повреждая локальные поля даты и времени.
  • Теперь фильтр импорта PDF имеет явные вспомогательные функции для ASCIIHexDecode, ASCII85Decode и RunLengthDecode, а значение EarlyChange по умолчанию для LZWDecode теперь соответствует значению по умолчанию в PDF (1). Это улучшает совместимость с импортированными или скопированными страницами, использующими устаревшие фильтры потоков PDF.

2026-05-21 Version 2.119.32

  • В версии v2.85.0, функция обязательного объединения лигатур для арабской буквы LAM теперь реализована в шейпере на стороне генерации. При включенной функции AutoShapeArabic, любая последовательность символов U+0644 LAM (в исходной форме или в любой из четырех ее вариантов) за которой следует один из четырех вариантов символа ALEF (MADDA U+0622, HAMZA-above U+0623, HAMZA-below U+0625, обычный U+0627; в исходной или после преобразования форме), объединяется в одну лигатурную глифу из блока U+FEF5-U+FEFC. Форма лигатуры (связанная или изолированная) выбирается в зависимости от того, была ли буква LAM преобразована в конечную (FEDE) или медиальную (FEE0) форму. Другие обязательные арабские лигатуры (Allah U+FDFB и декоративные лигатуры) по-прежнему требуют полноценного движка GSUB и не входят в область действия модели статической таблицы. Текст, не содержащий LAM-ALEF, и вызовы AutoShapeArabic, отключенные, остаются идентичными по байтам с выводом версии v2.119.31. Три вспомогательные функции AcroForm Unicode /AP (однострочная, многострочная, комбинированная) автоматически наследуют это изменение через общий пункт входа _ApplyArabicShaping.

2026-05-21 Version 2.119.31

  • Новый адаптер экспорта для системы ExpressPrinting от DevExpress: `dxHotPDFExportReportLinkToFile` / `dxHotPDFExportReportLinkToStream` принимает любой объект `TBasedxReportLink` (абстрактный класс, связывающий такие компоненты, как cxGrid, cxRichEdit, cxScheduler, cxPivotGrid и другие компоненты, предназначенные для печати, с `TdxComponentPrinter`) и передает каждую отрисованную страницу в HotPDF вместо собственного модуля `dxPSExportToPDF` от DevExpress. Этот адаптер повторяет внутренний цикл экспорта DevExpress: перестраивает отчет → для каждой страницы → отрисовывает страницу на `TMetafileCanvas` → отображает улучшенный метафайл в HotPDF. Области параметров позволяют указать заголовок, автора, тему, ключевые слова, версию PDF, сжатие и разрешение отрисовки. Этот адаптер имеет те же ограничения, что и адаптеры для FastReport, QuickReport и ReportBuilder: нет полей форм AcroForm, нет оглавлений, нет поддержки PDF/A или PDF/X. Адаптер находится в каталоге `Lib/Addons/DevExpress/` и не включен в основной файл `HotPDF*.dpk`.

2026-05-20 Version 2.119.30

  • Добавлен новый класс устройства ReportBuilder: `TppHotPDFDevice`, который наследуется от `TppGraphicsDevice` и подключается к стандартной цепочке "издатель → устройство" в ReportBuilder, когда назначается `TppReport.PrinterDevice` или `TppPublisher.Device`. Каждая страница отрисовывается на временном холсте метафайла (`TMetafileCanvas`, создаваемом в `BeforeRenderPage` и завершаемом в `AfterRenderPage`), захватывается как метафайл и передается через импортер EMF HotPDF (`HPDFEmf.ShowEnhancedMetafile`). Свойства позволяют указать заголовок, автора, тему, ключевые слова, версию PDF и уровень сжатия. `SetOutputStream` направляет байты PDF в поток, предоставленный вызывающим кодом. Как и в адаптерах FastReport/QuickReport, существуют ограничения: недоступны поля AcroForm, оглавления, а также поддержка PDF/A и PDF/X. Этот адаптер находится в каталоге `Lib/Addons/ReportBuilder/` и не включен в основной пакет `HotPDF*.dpk`.

2026-05-20 Version 2.119.29

  • Добавлен новый фильтр экспорта QuickReport: `TQRHotPDFExportFilter` наследуется от `TQRExportFilter`, поэтому он интегрируется в обычный процесс `MyReport.ExportToFilter(MyFilterInstance)` без внесения изменений в основную функциональность QuickReport. Этот адаптер извлекает метафайлы для каждой страницы, которые QuickReport уже сохраняет в `QRPrinter.PageList`, и передает каждый из них в импортер EMF от HotPDF (`HPDFEmf.ShowEnhancedMetafile`). Свойства позволяют указать заголовок, автора, тему, ключевые слова, версию PDF и уровень сжатия. `SetOutputStream` направляет байты PDF в поток, предоставленный вызывающей стороной, вместо записи на диск. Как и в случае с адаптером FastReport, существуют ограничения: недоступны поля форм AcroForm, оглавления, а также поддержка PDF/A и PDF/X. Адаптер находится в каталоге `Lib/Addons/QuickReport/` и не включен в основной пакет `HotPDF*.dpk`.

2026-05-20 Version 2.119.28

  • Новый адаптер экспорта FastReport 4 / FastReport VCL: `TfrxHotPDFExport` наследуется от `TfrxCustomExportFilter`, поэтому он интегрируется в обычный процесс `MyReport.Export(MyExportInstance)` без изменений в основном коде FastReport. Адаптер передает каждую подготовленную страницу в импортер EMF от HotPDF (через `TfrxPreviewPages.DrawPage → TMetafileCanvas → HotPDF.ShowEnhancedMetafile`), поэтому векторный и растровый контент страницы, отрисованный стандартным движком компоновки FastReport, сохраняется без необходимости генерировать код для каждого отдельного объекта. Свойства позволяют настроить такие параметры, как заголовок, автор, тема, ключевые слова, версия PDF и уровень сжатия, а также разрешение отрисовки (DPI) для управления результатом. Ограничения: отсутствие полей форм AcroForm, отсутствие очертаний, отсутствие поддержки PDF/A / PDF/X (для этого требуется конвейер генерации кода для каждого объекта, запланирован для будущей версии). Адаптер находится в каталоге `Lib/Addons/FastReport4/` и НЕ включен в основной файл `HotPDF*.dpk`; пользователи должны добавить его в свой проект вместе с соответствующим пакетом FastReport.

2026-05-20 Version 2.119.27

  • Новая сквозная подпись PDF на основе PFX: `THotPDF.SignPDFWithPFX(InputPDFPath, OutputPDFPath, PFXFilePath, Password)` загружает PDF-файл без подписи, который уже содержит заполнитель `AddSignedSignatureField`, анализирует файл PFX / PKCS#12, создает полную структуру CMS SignedData (RFC 5652) для указанных байтов и записывает подписанный PDF-файл за один вызов. Также предоставляется вариант с использованием потока `TStream` для работы в памяти. Размер поля `/Contents` в PDF должен быть достаточно большим, чтобы вместить шестнадцатеричные данные CMS; по умолчанию 8192 байта обеспечивают поддержку RSA с длиной ключа 1024/2048 бит. Поддерживаются только файлы PFX, использующие PBES2 + AES-256-CBC (ограничение парсера PKCS#12 версии v2.119.26).
  • Добавлен новый модуль HPDFCMS: конструктор SignedData для CMS. HPDFCMSBuildSignedData создает структуру ContentInfo → SignedData → SignerInfo, используя отсоединенный контент, атрибуты contentType, messageDigest и signingTime (отсортированные в порядке возрастания DER согласно RFC 5652 §5.4). Идентификатор SignerInfo (IssuerAndSerialNumber) извлекается из сертификата X.509, используется алгоритм RSA + SHA-256, а сам сертификат X.509 обернут в [0] неявные сертификаты. Также добавлены HPDFCMSSHA256ByteRanges для вычисления дайджеста в двух окнах и HPDFCMSBytesToHex для вставки заполнителей в /Contents. Это завершает цепочку модулей для подписи, начатую с HPDFASN1 (v2.119.23), HPDFRSA (v2.119.24), расширений HPDFCrypt (v2.119.25) и HPDFPFX (v2.119.26).

2026-05-20 Version 2.119.26

  • Добавлен новый модуль HPDFPFX: парсер контейнеров PKCS#12 / PFX. Он считывает файлы .pfx / .p12 из OpenSSL ≥ 3.0, certutil (Windows 11+) и Keychain Access (macOS), расшифровывает зашифрованные данные SafeBag с использованием алгоритма PBES2 (PBKDF2-HMAC-SHA-256 + AES-256-CBC) и извлекает параметры X.509 сертификата в формате DER и закрытого ключа RSA. Возвращается запись THPDFPFXKeyMaterial, содержащая CertDER, Modulus, PublicExponent и PrivateExponent, которые могут быть напрямую использованы кодом CMS / подписи. Неправильный пароль обнаруживается по ошибке отмены заполнения PKCS#7, возникающей при использовании неверного ключа AES. Для устаревших файлов PBE-SHA1-3DES отображается сообщение с рекомендацией повторного экспорта с использованием параметров `-keypbe AES-256-CBC -certpbe AES-256-CBC`.

2026-05-20 Version 2.119.25

  • Добавлены новые криптографические примитивы: обратный шифр AES-256 с AES256DecryptBlock + AES256CBCDecryptPKCS7 + AES256CBCDecryptNoPad (в соответствии с FIPS-197 §5.3, дополняя существующие функции шифрования), HMAC-SHA-256 (RFC 2104) и PBKDF2-HMAC-SHA-256 (RFC 8018 §5.2). Проверено соответствие векторам HMAC, определенным в RFC 4231, и стандартным результатам для PBKDF2-SHA-256. Вместе с декодером ASN.1 версии v2.119.23 и примитивами RSA версии v2.119.24, это завершает криптографическую основу, необходимую для безопасного дешифрования SafeBag, используемого в современных файлах PKCS#12 / PFX (OpenSSL ≥ 3.0 / Windows 11+).

2026-05-20 Version 2.119.24

  • Добавлен новый модуль HPDFRSA: реализована арифметика целых чисел произвольной точности, RSA-модульное возведение в степень и кодирование EMSA в соответствии со стандартом PKCS#1 v1.5. Этот модуль достаточно мощный для использования с реальными RSA-ключами длиной 2048/4096 бит. Вместе с декодером ASN.1, представленным в версии v2.119.23, это завершает набор криптографических примитивов, необходимых для предстоящей системы подписи PDF-файлов на основе PFX, которая будет реализована непосредственно в библиотеке. На данный момент ни один из пользовательских API не использует этот модуль; это внутренняя инфраструктура, ожидающая добавления слоев PKCS#12 и CMS.

2026-05-20 Version 2.119.23

  • Добавлен новый модуль HPDFASN1: компактный декодер для подмножества ASN.1, необходимый для чтения хранилищ ключей PKCS#12, сертификатов X.509 и контейнеров CMS/PKCS#7 SignedData, которые требуются HotPDF. Предоставляет доступ к THPDFASN1Node (описателю Tag-Length-Value), THPDFASN1ParseNode, методам ParseAt, Content, ToInteger, ToBigInt, ToOID, ToString, а также итераторам FirstChild, NextSibling и Children. Явно отклоняет BER с неопределенной длиной и кодировки с номерами тегов, превышающими 30, что соответствует строгому подмножеству DER. Это внутренняя инфраструктура для конвейера подписи PFX, который появится в будущих версиях — на данный момент ни один API, используемый пользователями, не зависит от него.

2026-05-20 Version 2.119.22

  • Добавлены новые перегрузки для аннотаций PolyLine и Polygon с полной информацией: методы THPDFPage.AddPolylineAnnotation и AddPolygonAnnotation теперь принимают массив вершин THPDFCurrPoint и необязательную запись THPDFPolyExtras. Эта запись предоставляет доступ к необязательным полям, определенным в ISO 32000-1 §12.5.6.9, таким как цвет заливки (/IC), облачный контур (/BE с параметрами /I для интенсивности), назначение (/IT: PolyLineDimension, PolyLineFlight, PolygonCloud, PolygonDimension) и стили окончания линии (/LE) для PolyLine. Используйте HPDFDefaultPolyExtras() для создания записи с начальными значениями. Новые перегрузки проверяют, что передано не менее двух вершин, и автоматически увеличивают версию документа (PDF 1.5 / 1.6 / 1.7 в зависимости от назначения). Предыдущие перегрузки, использующие interleaved-Single, продолжают компилироваться без изменений.

2026-05-20 Version 2.119.21

  • Новые возможности для аннотации "Линия": функция `AddLineAnnotation` получила третью перегрузку, принимающую структуру `THPDFLineExtras`, которая управляет необязательными элементами, описанными в таблице 175 раздела §12.5.6.7 стандарта PDF 1.6/1.7 — /IC (цвет внутренней части, заполненные стрелки, ромбы и т.д.), /LL (длина направляющей линии), /LLE (удлинение направляющей линии), /LLO (смещение направляющей линии, PDF 1.7), флаг /Cap (с параметром /CP: /Inline или /Top, PDF 1.7) и смещение /CO, а также /IT (назначение: LineArrow / LineDimension). Используйте `HPDFDefaultLineExtras()` для инициализации структуры значениями по умолчанию. Новая перегрузка автоматически повышает версию документа до PDF 1.6 (или 1.7, если запрошены параметры /LLO, /CP и /CO). Две предыдущие перегрузки продолжают генерировать идентичный по байтам вывод, и записываются только те элементы, которые явно запрошены вызывающим кодом.

2026-05-20 Version 2.119.20

  • Добавлены новые действия кнопок "baShow" и "baImportData": класс `THPDFButtonAction` теперь включает `baShow` (аналогично `baHide`, который устанавливает значение `/H` в `false` для повторного отображения скрытого элемента управления) и `baImportData` (`/S /ImportData /F filespec` для загрузки данных формы FDF при нажатии, согласно ISO 32000-1 §12.7.5.4). Действие `baShow` разрешено спецификацией PDF/A и PDF/X; действие `baImportData` запрещено обоими стандартами в соответствии с ISO 19005-1 §6.6.1 и ISO 15930 для предварительной обработки, соответственно.
  • Новая перегрузка функции `THPDFPage.AddPushButtonWithHideAction`: `THPDFPage.AddPushButtonWithHideAction(FieldName, Caption, Targets, Hide, Rectangle, Flags)` принимает массив имен целевых полей и явное булево значение `Hide`, что позволяет одной кнопке переключать видимость нескольких виджетов одним щелчком. Если массив `Targets` пуст, возникает исключение. Как PDF/A, так и PDF/X поддерживают эту перегрузку (только видимость виджетов).

2026-05-20 Version 2.119.19

  • Добавлен новый элемент управления пользовательского интерфейса SubmitForm /Flags: THPDFPage.AddPushButtonWithSubmitAction(FieldName, Caption, URL, Rectangle, SubmitFlags) предоставляет полный набор флагов, определенных в таблице 237 раздела 12.7.5.2 стандарта ISO 32000-1, с помощью нового типа данных THPDFSubmitFormFlags. Теперь пользователи могут комбинировать флаги, такие как sffExportFormatHTML, sffXFDF, sffSubmitPDF (формат отправки), sffGetMethod (HTTP GET или POST), sffIncludeAnnotations, sffSubmitCoordinates, sffCanonicalFormat, sffIncludeNoValueFields, sffIncludeAppendSaves, sffExclNonUserAnnots, sffEmbedForm и другие, заменяя жестко закодированное значение /Flags 0 (FDF + POST) в устаревшем пути baSubmitURL. Существующий метод AddPushButtonWithAction(.., baSubmitURL, ..) по-прежнему генерирует /Flags 0 для обеспечения совместимости на уровне байтов. Действуют те же ограничения для PDF/A и PDF/X, что и для baSubmitURL: разрешено для PDF/A, заблокировано для PDF/X.

2026-05-20 Version 2.119.18

  • Расширенные типы действий для кнопок: THPDFButtonAction теперь включает в себя baNamed и baHide. baNamed генерирует действие /S /Named /N (ISO 32000-1 §12.6.4.11), подходящее для четырех стандартных команд навигации: NextPage, PrevPage, FirstPage и LastPage (PDF/A допускает все четыре, согласно ISO 19005-1 §6.6.1), а также для расширений Acrobat, таких как Print и SaveAs. baHide генерирует действие /S /Hide /T /H true (§12.6.4.10), которое скрывает указанное поле формы при нажатии на кнопку. Оба типа действий разрешены в спецификациях PDF/A и PDF/X; только baJavaScript, baResetForm и baSubmitURL сохраняют существующие ограничения соответствия.

2026-05-20 Version 2.119.17

  • Добавлен новый реестр именованных ссылок: `THotPDF.RegisterNamedDestination(Name, PageIndex, FitMode, ...)` регистрирует символьную ссылку в дереве имен `/Names /Dests` (ISO 32000-1 §12.3.2.3). Теперь действия "Перейти" / "Перейти к" и записи `/Dest` в оглавлении могут ссылаться на ссылку по имени, а не на жестко закодированные номера страниц, что обеспечивает стабильность перекрестных ссылок при вставке, удалении или переупорядочивании страниц. Новый перечислитель `THPDFDestinationFitMode` охватывает все восемь режимов масштабирования, определенных в спецификации. Метод вызывает исключение в случае пустой строки `Name`, недопустимого значения `PageIndex` или дублирования `Name`; при необходимости автоматически обновляет версию документа до PDF 1.2. Отсутствует ограничение для PDF/A / PDF/X — средства навигации разрешены во всех профилях.

2026-05-20 Version 2.119.16

  • Добавлены новые стили окончания линии для аннотаций /LE: Метод THPDFPage.AddLineAnnotation теперь имеет перегрузку, принимающую параметры для определения стилей начала и окончания линии. Полный набор, определенный в таблице 176 раздела §12.5.6.7 стандарта ISO 32000-1, теперь доступен через новый перечисляемый тип THPDFLineEndingStyle: None, Square, Circle, Diamond, OpenArrow, ClosedArrow, Butt, ROpenArrow, RClosedArrow, Slash. Теперь аннотации линий могут отображаться в виде правильных стрелок, маркеров размеров или указателей внутри Adobe Acrobat / Foxit без необходимости ручной отрисовки кончиков стрелок на странице. Предыдущая версия с четырьмя параметрами по-прежнему работает без изменений.

2026-05-20 Version 2.119.15

  • Новая стилизация для структуры (закладок): THPDFDocOutlineObject теперь предоставляет свойства Color, Bold и Italic (ISO 32000-1 §12.3.3 Таблица 153 /C и /F). Панель структуры теперь может отображать закладки в цвете, а также жирным или курсивным шрифтом, что полезно для группировки глав, выделения неполных или требующих внимания разделов и соответствия фирменному стилю. Цвет по умолчанию равен clNone (не генерируется запись /C, идентична предыдущему выводу); Bold и Italic по умолчанию установлены в false. Установка свойств после вызова AddChild обновляет активный словарь структуры на месте, а установка свойства Color в clNone или свойств Bold и Italic в false удаляет записи /C и /F.

2026-05-20 Version 2.119.14

  • Добавлен новый реестр JavaScript на уровне документа: теперь THotPDF предоставляет функцию RegisterDocumentJavaScript(Name, Body). Каждая зарегистрированная запись сериализуется в дерево каталогов /Names /JavaScript (ISO 32000-1 §7.7.4.4 + §12.6.4.16) в виде непрямого словаря /S /JavaScript /JS. Действия виджетов AcroForm и действия при открытии документа могут вызывать зарегистрированную функцию по имени через JavaScript-движок просмотрщика (Acrobat, Foxit). Это полезно для обмена библиотекой функций для проверки, форматирования или вычислений между многими виджетами, не дублируя исходный код JavaScript в каждом словаре действий /A. Этот метод вызывает ошибку при любом уровне соответствия PDFA (ISO 19005-1 §6.6.1) и любом уровне соответствия PDFX (ISO 15930 prepress workflows) и отклоняет пустые значения Name / Body, а также повторную регистрацию Name.

2026-05-20 Version 2.119.13

  • Добавлена поддержка миниатюр страниц: теперь `THPDFPage` предоставляет методы `SetPageThumbnail(ImageIndex)` и `ClearPageThumbnail`. Программы просмотра PDF-файлов (Acrobat, Foxit, встроенные просмотрщики браузеров) используют запись `/Thumb` на странице (ISO 32000-1 §12.3.4) для отображения предварительного просмотра в панели навигации без растеризации страницы, что особенно полезно для архивов с большим количеством изображений, где собственный растеризатор программы просмотра работал бы медленно. Вспомогательный модуль повторно использует любые изображения, зарегистрированные с помощью `AddImage` / `AddImageFromFile`, поэтому вызывающий код может подготовить уменьшенную версию изображения и прикрепить ее одним вызовом; `SetPageThumbnail(-1)` или `ClearPageThumbnail` удаляют ранее прикрепленную миниатюру. В случае указания недопустимого индекса изображения возникает информативное исключение.

2026-05-20 Version 2.119.12

  • Исправлена проблема соответствия стандарту PDF/A: функция AddPushButtonWithAction теперь вызывает исключение, когда используются типы действий baJavaScript или baResetForm при любом уровне соответствия стандарту PDFACompliance (PDF/A-1/2/3). Стандарты ISO 19005-1 §6.6.1, ISO 19005-2 §6.5.1 и ISO 19005-3 §6.5.1 запрещают использование действий JavaScript, ResetForm и ImportData во всех версиях PDF/A. Действия baSubmitURL (SubmitForm), baURI и baNone по-прежнему разрешены в PDF/A — действие SubmitForm включено в список разрешенных действий в §6.6.1. Ранее кнопки могли содержать запрещенные действия, даже если PDFACompliance был включен, поскольку защита v2.119.5 распространялась только на пути Catalog /AA и OpenAction на уровне документа.
  • Исправлена проблема соответствия стандарту PDF/X: функция AddPushButtonWithAction теперь выдает ошибку, если используются типы действий baJavaScript, baResetForm или baSubmitURL при любом уровне соответствия стандарту PDF/X. Рабочие процессы предварительной обработки, соответствующие стандарту ISO 15930, исключают интерактивное программирование, изменение форм и отправку данных форм на внешние ресурсы.

2026-05-20 Version 2.119.11

  • Исправлена проблема соответствия стандарту PDF/A: типы аннотаций PDF/A теперь корректно обрабатываются. Функции `AddScreenAnnotation`, `Add3DAnnotation` и `AddRichMediaAnnotation` теперь выдают ошибку, если включена проверка соответствия PDF/A на любом уровне (PDF/A-1/2/3). Стандарты ISO 19005-1 §6.5.2, ISO 19005-2 §6.6.1 и ISO 19005-3 §6.6.1 запрещают использование аннотаций типа Screen, 3D и RichMedia (мультимедиа / расширение Adobe уровня 3) во всех версиях PDF/A. Аналогичные ограничения применяются при проверке соответствия стандарту PDF/X — этапы предварительной обработки, соответствующие стандарту ISO 15930, не поддерживают аннотации типа мультимедиа.
  • Исправлена проблема соответствия стандарту PDF/A-1: функции `AddWatermarkAnnotation` и `AddRedactAnnotation` теперь выдают ошибку, когда `PDFACompliance` установлено в значение PDF/A-1. Водяные знаки (PDF 1.6) и функции закрашивания (PDF 1.7) являются подтипами аннотаций, несовместимыми с базой PDF 1.4 стандарта PDF/A-1 (ISO 19005-1 §6.5.2). Соответствие стандартам PDF/A-2 и PDF/A-3 (основанные на PDF 1.7) по-прежнему допускает оба типа аннотаций.

2026-05-20 Version 2.119.10

  • Исправлена проблема соответствия стандарту PDF/A: методы `AddImageWithSMask` и `AddImageWithSMask32` теперь выдают исключение, когда `PDFACompliance` установлено в значение PDF/A-1. ISO 19005-1:2005, раздел 6.4, запрещает все эффекты прозрачности; поток `/SMask` для изображения активирует композицию прозрачности. Предварительно объедините изображение с фоновым цветом и передайте результат в `AddImage()`, или используйте PDF/A-2 или более позднюю версию для поддержки прозрачности. PDF/A-2 и PDF/A-3 по-прежнему допускают использование мягкой маски для прозрачности изображений.

2026-05-20 Version 2.119.9

  • Исправлена проблема соответствия стандарту PDF/A: методы SetTransparencyGroup и SetTransparencyGroupICC теперь выдают исключение, когда PDFACompliance установлено в значение PDF/A-1. ISO 19005-1:2005, раздел 6.4, запрещает все эффекты прозрачности; группы прозрачности на уровне страницы (page /Group /S /Transparency dict) активируют модель композиции прозрачности для всей страницы, что является прямым нарушением раздела 6.4. Соответствие стандартам PDF/A-2 и PDF/A-3 по-прежнему допускает группы прозрачности на уровне страницы.

2026-05-20 Version 2.119.8

  • Исправлена проблема соответствия стандарту PDF/A: теперь функция RegisterHalftoneState вызывает исключение, когда активен режим PDFACompliance и предоставлен пользовательский словарь полутонов (то есть, HTDefaultName = false). Согласно ISO 19005-1:2005 §6.2.9 и ISO 19005-2:2011 / ISO 19005-3:2012 §6.3.7, разрешено использовать только строковый литерал "/Default" для ExtGState /HT; пользовательские словари полутонов (типов 1, 5, 6, 10, 16) запрещены. Передача значения HTDefaultName=True для возврата к значению по умолчанию продолжает работать во всех версиях PDF/A.
  • Исправлена проблема соответствия стандарту PDF/A: теперь функция RegisterSoftMaskState вызывается, когда PDFACompliance установлено в значение PDF/A-1 и предоставлен пользовательский словарь маски (параметр SMaskDict). ISO 19005-1:2005 §6.4 запрещает все эффекты прозрачности; значение /SMask, отличное от None, активирует прозрачность маски. Возможность передачи SMaskNone=True для сброса масок остается доступной. Соответствие стандартам PDF/A-2 и PDF/A-3 по-прежнему допускает использование прозрачности маски.

2026-05-20 Version 2.119.7

  • Исправлена проблема соответствия стандарту PDF/A: функция AddDocumentAttachment (встраивание файлов на уровне документа через Catalog /Names /EmbeddedFiles) теперь вызывает ошибку, когда PDFACompliance включена для PDF/A-1 или PDF/A-3. ISO 19005-1:2005 §6.1.11 явно запрещает использование ключа /EmbeddedFiles в словаре Names документа для PDF/A-1. Для PDF/A-3, встраиваемые файлы должны быть зарегистрированы с помощью функции AddPDFA3AssociatedFile(), чтобы включить необходимый массив /AF и ключ /AFRelationship, как указано в ISO 19005-3:2012 Приложении E. PDF/A-2 по-прежнему допускает встраивание файлов, при условии, что сами встраиваемые файлы соответствуют стандарту PDF/A.

2026-05-20 Version 2.119.6

  • Исправлена проблема соответствия стандарту PDF/A: теперь, при использовании стандартных шрифтов (Arial, Helvetica, Times New Roman, Courier New, Symbol, ZapfDingbats) с включенной опцией StandardFontEmulation, возникает информативное исключение, когда активен режим PDFACompliance. ISO 19005-1:2005 §6.3 и ISO 19005-2:2011 / ISO 19005-3:2012 §6.3 требуют, чтобы все шрифты были встроены в соответствующие файлы; путь эмуляции стандартных шрифтов создает ссылку на шрифт, который не встроен, что является прямым нарушением §6.3. Пользователям следует установить StandardFontEmulation := false или использовать RegisterUnicodeTTF() с фактическими файлами шрифтов для создания файлов, соответствующих стандарту PDF/A.
  • Исправлена проблема соответствия стандарту PDF/A: нестандартные шрифты теперь всегда встраиваются, когда активна функция PDFACompliance, независимо от настройки свойства FontEmbedding. Оптимизация FontEmbedding = false автоматически отключается в режиме PDF/A для соответствия требованию §6.3 о встраивании всех шрифтов.

2026-05-20 Version 2.119.5

  • Исправлена проблема соответствия стандарту PDF/A: действия JavaScript и элементы /AA (дополнительные действия) на уровне каталога теперь блокируются, когда активна функция PDFACompliance. ISO 19005-1:2005 §6.6.1/§6.6.2 и ISO 19005-2:2011 / ISO 19005-3:2012 §6.5.1/§6.6.2 запрещают все типы действий JavaScript и запрещают использование ключа /AA в словаре каталога. Теперь вызов SetActionScript с любым значением PDFACompliance вызывает исключение с описанием ошибки. В качестве дополнительной меры защиты, пути выполнения JavaScript для OpenAction и элемента /AA в разделе EndDoc также заблокированы, чтобы молчаливо пропускать вывод, когда активна функция PDFACompliance, что гарантирует, что даже через внутренние пути не будут записаны не соответствующие стандарту ключи.

2026-05-20 Version 2.119.4

  • Исправлена проблема соответствия стандарту PDF/A: теперь параметр AcroForm /NeedAppearances всегда устанавливается в значение false, когда активен режим PDFACompliance, независимо от настройки AutoFormAppearances. В соответствии с требованиями ISO 19005-1:2005 §6.9 и ISO 19005-2:2011 / ISO 19005-3:2012 §6.4, этот параметр должен отсутствовать или иметь значение false в файлах, соответствующих стандарту. Ранее, если AutoFormAppearances был отключен при активном режиме PDFACompliance, параметр /NeedAppearances устанавливался в значение true, что приводило к созданию файла, не соответствующего стандарту.

2026-05-20 Version 2.119.3

  • Исправлена проблема соответствия стандарту PDF/A: теперь встроенные подмножества CIDFont включают в себя поток /CIDSet в описателе шрифта, когда активна функция PDFACompliance. ISO 19005-1:2005 §6.3.5 и ISO 19005-2:2011 / ISO 19005-3:2012 §6.2.11 требуют, чтобы подмножества CIDFont содержали битстрим /CIDSet, указывающий, какие значения CID присутствуют в программе встроенного шрифта. HotPDF использует кодировку Identity-H, где CID равен коду Unicode, поэтому битстрим /CIDSet создается непосредственно из набора используемых в документе кодов Unicode. Битстрим сжимается с помощью FlateDecode и добавляется к существующему описателю шрифта в виде объекта потока. Это исправляет ранее не обнаруженную проблему, присутствовавшую во всех версиях PDF/A (ранее проверка соответствия ошибочно указывала, что это уже реализовано).

2026-05-20 Version 2.119.2

  • Исправлена проблема соответствия стандартам PDF/A-2 и PDF/A-3: словарь внешнего вида аннотаций (/AP /N) теперь автоматически создается для типов аннотаций, не являющихся ссылками и всплывающими окнами (TextNotes, FreeText, Line, Square, Circle, Stamp, FileAttachment), когда PDFACompliance установлено на уровень PDF/A-2 или PDF/A-3. ISO 19005-2:2011 §6.3.3 и ISO 19005-3:2012 §6.3.3 требуют, чтобы каждая такая аннотация имела хотя бы один словарь внешнего вида (с формой XObject, содержащей запись "N"). Создается минимальный пустой объект формы XObject для удовлетворения структурного требования; большинство просмотрщиков PDF используют собственную встроенную отрисовку для стандартных типов аннотаций, независимо от содержимого потока /AP. Аннотации, являющиеся ссылками и всплывающими окнами, явно исключены из этого требования и остаются без изменений. Это требование не применяется к PDF/A-1 (ISO 19005-1 §6.5.3 ограничивает только формат /AP, если он присутствует, а не его наличие).

2026-05-20 Version 2.119.1

  • Исправлена проблема соответствия стандарту PDF/A: теперь все типы аннотаций, отличные от виджетов (текстовые заметки, штампы, линии, фигуры, гиперссылки, ссылки GoTo, ссылки GoToR, ссылки URI), автоматически устанавливают флаг печати "/F" (бит 3 = 1, значение 4), когда активна функция PDFACompliance. Согласно ISO 19005-1:2005 §6.5.3 и ISO 19005-2:2011 / ISO 19005-3:2012 §6.3.2, каждый словарь аннотаций должен содержать ключ "/F" с установленным битом печати. Ранее этот флаг присутствовал только у аннотаций виджетов (полей форм); все остальные типы аннотаций его не имели, что делало создаваемые файлы несоответствующими стандарту.
  • Исправлена проблема соответствия стандарту PDF/A-1: группы необязательного содержимого (слои) теперь блокируются, когда параметр PDFACompliance установлен на уровень PDF/A-1 ('A' или 'B'). ISO 19005-1:2005 §6.1.13 запрещает использование ключа /OCProperties в словаре Catalog; теперь, при вызове RegisterOptionalContentGroup в режиме PDF/A-1, возникает информативное исключение, которое рекомендует пользователям использовать PDF/A-2 или более позднюю версию, если требуется необязательное содержимое. Также, вывод элемента /OCProperties в конце документа теперь отключен, чтобы предотвратить неявное несоответствие, даже если группы необязательного содержимого были зарегистрированы.

2026-05-20 Version 2.119.0

  • Поддержка контейнера XAdES-in-PDF в соответствии со стандартом ETSI EN 319 142-2 V1.2.0 §6.2 (завершение серии B/C/D, часть 3). Встраивает предоставленные вызывающей стороной байты XML, подписанные XAdES, как PDF EmbeddedFile, регистрирует Filespec в массиве /AF, устанавливает /AFRelationship в соответствии с перечислением PDF 2.0, указанным вызывающей стороной. Это только обертка на стороне производителя; фактическое создание подписи XAdES (XML-DSig + квалификационные свойства ETSI EN 319 132-1 + временная метка RFC 3161, встроенная в xades:UnsignedSignatureProperties) является ответственностью вызывающей стороны и ее XML-криптографической библиотеки (например, Apache Santuario, .NET SignedXml, libxmlsec, Saxon с расширениями XAdES и т.д.).
  • Добавлен новый метод `THotPDF.AddXAdESAssociatedFile(FileName, XMLBytes, Description, MimeType, Relationship)`. Значения по умолчанию: MimeType - `'application/xml'` (также часто используется `'application/vnd.etsi.asic-e+zip'` для архивов ASiC-E), Relationship - `'Source'` (XML-файл, подписанный XAdES, является основным содержимым документа). Метод возвращает словарь indirect Filespec, чтобы вызывающий код мог добавить дополнительные метаданные или создать перекрестные ссылки из пользовательских записей каталога.
  • Независимо от PDF/A: в отличие от функции `AddPDFA3AssociatedFile` в версии v2.108 (которая требует установки PDFACompliance='3*'), этот вспомогательный инструмент не имеет ограничений, связанных с PDF/A — использование XAdES в PDF является отдельной группой профилей, согласно стандарту PAdES Part 2 V1.2.0 §6.
  • Исправлена критическая ошибка в функции `_EscapePDFNameBytes` (PDF 1.7, ISO 32000-1, §7.3.5 + Таблица 2). В предыдущей версии функция преобразовывала только байты, выходящие за пределы диапазона [0x21..0x7E] и символ `#`; разделители PDF (`/ ( ) < > [ ] { } %`), которые в соответствии со спецификацией должны быть представлены в виде `#XX` внутри имен, оставались неизменными. В результате, строгие парсеры интерпретировали имена, такие как `/Subtype /application/xml`, как два отдельных имени ( `/application`, за которым следует `/xml`), что приводило к сбою распознавания `EmbeddedFile /Subtype`. В версии 2.119 все 10 разделителей преобразуются в соответствии со спецификацией; имена, не являющиеся разделителями (что составляет подавляющее большинство данных, генерируемых HotPDF), остаются без изменений. Теперь MIME-типы, определенные в приложении E стандарта PDF/A-3 (версия 2.108), генерируются правильно (`/application#2Fxml` вместо некорректного `/application/xml`).
  • Серия PAdES B/C/D была завершена с 3 коммитами: v2.117 (расширенные профили E-BES / E-EPES / E-LTV в соответствии с частью 2, §5) + v2.118 (значения инициализации в соответствии с ISO 32000-1, §12.7.5.5 + частью 2, §4.2.6) + v2.119 (XAdES-in-PDF + исправление проблемы с экранированием разделителей в соответствии с частью 2, §6.2). Вместе с версиями v2.109 - v2.116, HotPDF теперь охватывает полный спектр возможностей PAdES, включая базовые профили, расширенные профили, временные метки документов, информацию о проверке DSS, расширения ESIC, ограничения подписи с использованием значений инициализации и контейнер XAdES-in-PDF.
  • Win32 + Win64: чистая сборка; базовые версии v2.108 - v2.118 пересобраны без изменений. Добавлены новые тесты smoke для smoke_pades_xades, включающие 2 положительных сценария (XML с подписью XAdES в качестве /AFRelationship /Source и архив ASiC-E в качестве /Data) и 4 сценария отказа (пустое имя файла, пустые XML-данные, пустой MIME-тип, неверная связь). Python-валидатор проверяет оба файла от начала до конца, включая варианты `/Subtype /application#2Fxml` и `/Subtype /application#2Fvnd.etsi.asic-e+zip`. Тесты smoke для PDF/A-3 / PAdES / PDF/X версии v2.108 запущены повторно и прошли успешно.

2026-05-20 Version 2.118.0

  • Значения начальных данных (Seed Values) в соответствии с 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 (шаг 2 из 3 для серий B/C/D). Словарь значений начальных данных (SV), прикрепленный к полю подписи, ограничивает возможности инструмента подписи, используемого читателем, для выбора параметров для этого конкретного поля, таких как обработчик, подфильтр, метод хеширования, является ли информация об отзыве обязательной, и какая минимальная версия PDF требуется.
  • Добавлен новый метод `THotPDF.AttachPAdESSeedValue(FieldName, SubFilters, DigestMethods, ForceSubFilter, ForceDigestMethod, AddRevInfo, MinPDFVersion, ForceMinPDFVersion)`. Он находит указанное поле подписи в списке полей AcroForm (которое должно быть предварительно создано с помощью вызова `AddPAdESSignatureField` или `AddDocumentTimestampSignature`) и добавляет к нему подсловарь `/SV` с ограничениями, предоставленными вызывающей стороной.
  • В записи Seed Value (согласно таблице 234):
    • `/Type /SV`
    • `/SubFilter` — массив имен (например, [/ETSI.CAdES.detached])
    • `/DigestMethod` — массив имен (например, [/SHA256 /SHA384 /SHA512])
    • `/AddRevInfo` — логическое значение; инструмент подписи должен включать OCSP/CRL в CMS
    • `/V` — число; минимальная версия PDF (например, 1.7)
    • `/Ff` — целочисленные битовые флаги (таблица 235); каждый параметр Force* устанавливает соответствующий бит, поэтому инструмент подписи ДОЛЖЕН соблюдать это ограничение (бит 2 = принудительно установить SubFilter, бит 3 = принудительно установить V, бит 6 = принудительно установить AddRevInfo, бит 7 = принудительно установить DigestMethod)
  • Правила обеспечения соответствия стандартам: раздел 4.2.6 спецификации PAdES Part 2 V1.2.0 запрещает использование значений, которые могут заставить инструменты подписи нарушать профиль PAdES (например, указание подфильтра PKCS#1). HotPDF не применяет это ограничение на стороне создателя – вызывающая сторона несет ответственность за передачу только допустимых значений, определенных стандартом (`'adbe.pkcs7.detached'` или `'ETSI.CAdES.detached'` для параметра SubFilter, SHA-256+ для параметра DigestMethod). В справочном комментарии явно указано это ограничение.
  • Чистая сборка для Win32 и Win64; все базовые версии от v2.108 до v2.117 были пересобраны без изменений. Новый тест smoke_pades_seedvalue создает поле PAdES-B-T, а затем применяет полный набор ограничений для Seed Value (SubFilter ограничен ETSI.CAdES.detached, DigestMethod ограничен SHA256/384/512, AddRevInfo установлен в true, MinPDFVersion установлен в 1.7, все биты принудительно установлены). Верификатор на Python проходит по подсловарю /SV и проверяет структуру каждого элемента; также проверяется сценарий отказа при использовании "неизвестного FieldName".
  • Серия, шаг 3 (v2.119): Контейнер XAdES-in-PDF, соответствующий части 2, версии 1.2.0, разделу 6, завершает серию B/C/D. На стороне производителя это тонкая обертка вокруг существующей инфраструктуры HotPDF для работы с внедренными файлами, каталогами и элементами формы (/AF), (v1.08, вспомогательный модуль PDF/A-3), а также семантики /AFRelationship, которые PAdES, часть 2, версия 1.2.0, раздел 6.2.2, ожидает для XML-пакетов, подписанных XAdES.

2026-05-20 Version 2.117.0

  • Расширенные профили PAdES в соответствии с ETSI EN 319 142-2 V1.2.0 §5 (шаг 1 из 3 для серий B/C/D). Базовый стандарт Part 1 (V1.2.1 §6 B-B / B-T / B-LT / B-LTA) определяет фиксированные комбинации атрибутов CMS; Part 2 §5 определяет параллельную группу "расширенных" профилей (E-BES / E-EPES / E-LTV) с большей гибкостью в отношении необязательных атрибутов CMS для пользователей, которым требуется большая гибкость, чем у базового стандарта (например, для корпоративных решений с несколькими политиками или для создания пользовательских профилей CAdES внутри оболочки PAdES).
  • `AddPAdESSignatureField`: Параметр профиля теперь принимает три дополнительных значения, помимо четырех основных:
    • `'E-BES'` — базовая и однозначная привязка к сертификату подписи с помощью атрибута ESS сертификата подписи (эквивалент CAdES-BES внутри конверта PAdES). Значение по умолчанию: 16 КБ для раздела /Contents.
    • `'E-EPES'` — E-BES + явный атрибут идентификатора политики подписи. Значение по умолчанию: 16 КБ; вызывающий обычно передает 18-20 КБ, чтобы вместить байты идентификатора объекта политики (OID) и квалификатора.
    • `'E-LTV'` — долгосрочная проверка с гибкой цепочкой сертификатов CMS-атрибутов + встроенная информация об отзыве. Автоматически увеличивается до 20 КБ (аналогично B-LT).
  • Формат передачи данных на стороне генератора одинаков как для базовых, так и для расширенных профилей — все используют подфильтр `ETSI.CAdES.detached`, одинаковую схему разграничения байтов и содержимого, а также одинаковую инфраструктуру DSS + ESIC (версии v2.110 / v2.116). Различие уровней заключается исключительно в структуре подписанных атрибутов CMS, которую создает криптографическая библиотека вызывающей стороны. Строка Profile отличается только диагностикой проверки и значением по умолчанию для раздела /Contents; HotPDF не кодирует CAdES-BES, CAdES-EPES или CAdES-T непосредственно в словаре PDF.
  • Обновлены комментарии в документации PAdES, описывающие обязанности вызывающей стороны, которые определены в части 2, версии 1.2.0, разделе 4.2: выбор хеша SHA-256 (завершение использования SHA-1), наличие только одного объекта SignerInfo для каждого поля Sig, отсутствие атрибутов сертификатов RFC 5755 и требование E-EPES включать подписанный атрибут signature-policy-identifier. Элементы, относящиеся к области ответственности вызывающей стороны, по-прежнему находятся вне зоны ответственности производителя, но контракт теперь явно определен на уровне API.
  • Чистая сборка для Win32 и Win64; базовые версии v2.108 - v2.116 полностью пересобраны без изменений. `smoke_pades_signature` расширен на 3 новых поля (SigEBES / SigEEPES / SigELTV), и каждое новое значение профиля проверяется через пути автоматического увеличения размера / явного бюджета / бюджета по умолчанию. Проверка на Python расширена для обработки всех 7 полей и проверяет расширение Catalog ESIC (перенесено из версии v2.116).
  • Шаг 2 серии B/C/D: версия 2.118 добавляет начальные значения (PDF 1.7 §12.7.5.5 + ETSI EN 319 142-1 V1.2.1 §5.5 + Часть 2 V1.2.0 §4.2.6), чтобы поля цифровой подписи PAdES могли указывать ограничения обработчика/SubFilter/метода хеширования, которым должен следовать программное обеспечение для чтения при подписании. Шаг 3: версия 2.119 добавляет поддержку контейнера XAdES-in-PDF в соответствии с Частью 2 V1.2.0 §6 (XML, подписанный XAdES, встроен как EmbeddedFile + ассоциация Catalog /AF).

2026-05-20 Version 2.116.0

  • Обновление PAdES в соответствии с последними нормативными версиями ETSI и решением о реализации eIDAS: ETSI EN 319 142-1 V1.2.1 (2024-01, опубликовано) + ETSI EN 319 142-2 V1.2.0 (2025-03, проект дополнительных профилей + расширенная группа профилей + XAdES-in-PDF) + ETSI TS 119 142-3 V1.1.1 (2016-12, PAdES-DTS Document Time-stamp) + EU 2015/1506 (признание в государственном секторе). Базовые версии HotPDF v2.109 - v2.111 (B-B / B-T / B-LT / B-LTA + автономная временная метка) по-прежнему соответствуют тому же формату; эта версия устраняет две проблемы, выявленные новыми версиями спецификаций.
  • В словарь DSS с ключом `/Type "DSS"` (EN 319 142-1 V1.2.1 §5.4.2.2). Элемент `/Type` является необязательным, но, если он присутствует, он должен иметь значение `/DSS`. Теперь HotPDF генерирует его немедленно, чтобы строгие валидаторы, которые проверяют `/Type` перед анализом остальной части словаря, могли сразу распознать структуру.
  • ESIC расширения словаря (TS 119 142-3 §5.1, рекомендуется). Новый метод `EnsurePAdESESICExtensions` безопасно записывает следующее в каталог каждый раз, когда вызывается помощник PAdES: `<< /Extensions << /ESIC << /BaseVersion /1.7 /ExtensionLevel 1 >> >> >>`. Валидаторы (Adobe Acrobat pre-flight, EU DSS, callas pdfaPilot) используют эту запись для идентификации документа как контейнера PAdES, объявляющего расширения уровня 1 для PDF 1.7 + ESIC.
  • Критическая исправление ошибки в пути двусторонней записи `EnsurePAdESDSS`. В версиях ниже v2.116, вспомогательный модуль повторно разрешал словарь DSS при каждом вызове с помощью `Catalog.GetIndexedItem(FindValue('DSS'))`, что возвращало ссылку на объект `THPDFLink`, а не сам словарь DSS. Неявное преобразование типа приводило к неправильному указателю, что приводило к тому, что все последующие вызовы `AddPAdESDSSCertificate` / `AddPAdESDSSOCSP` / `AddPAdESDSSCRL` / `AddPAdESDSSVRI` после первого вызова молча пропускали добавление элемента в массив (ссылка на массив разрешалась как null, `FindValue` возвращала -1, и срабатывал механизм раннего выхода `if-Idx-less-than-zero-Exit`). Исправление в v2.116 сохраняет ссылку на фактический словарь в поле `FPAdESDSSDict`, чтобы последующие вызовы использовали кэш. Тест `smoke_pades_dss` теперь правильно генерирует 2 сертификата + 1 OCSP + 1 CRL + 1 запись VRI (ранее только первый сертификат попадал в раздел /DSS, а массивы /OCSPs и /CRLs были пустыми).
  • Обновлены комментарии в документации для вспомогательных функций PAdES, касающиеся ответственности вызывающего кода, что было выявлено в разделе Part 2 V1.2.0 §4.2: вывод из эксплуатации SHA-1 (вызывающий код должен использовать SHA-256+ для CMS), наличие только одного объекта SignerInfo в PDF-сигнатуре (Part 2 §4.2.1 h / Part 1 §4.1 a), атрибутные сертификаты RFC 5755 не должны использоваться (Part 2 §4.2 g), и документы PAdES-DTS не должны содержать словари VRI (TS 119 142-3 §6.3 h — достаточно DSS). Формат данных, используемый HotPDF, уже соответствует всем четырем ограничениям по своей конструкции; комментарии информируют вызывающий код о том, что должны делать библиотеки для создания CMS.
  • Win32 + Win64: чистая сборка; тесты smoke_pades_signature, smoke_pades_dss, smoke_pades_doctimestamp и их верификаторы успешно пройдены. Расширения верификатора: smoke_pades_dss теперь проверяет наличие `/Type /DSS` и Catalog `/Extensions /ESIC /BaseVersion /1.7 /ExtensionLevel 1`; smoke_pades_doctimestamp проверяет то же расширение ESIC и принимает перевернутые по вертикали прямоугольники с нулевой площадью (`[0 H 0 H]`, где H - высота страницы). Документация и технические примечания обновлены с указанием ссылок на EN 319 142-1 V1.2.1 / Часть 2 V1.2.0 / TS 119 142-3 / EU 2015/1506.

2026-05-20 Version 2.115.0

  • PDF/X (ISO 15930): завершение серии обновлений (4/4): запрещены типы аннотаций и действий в соответствии с ISO 15930-1:2001 / ISO 15930-3:2002 / ISO 15930-7:2010 + ISO 32000-1 §12.5.6 / §12.6.4. Рабочие процессы печати PDF/X используют только видимый, печатаемый контент; мультимедийные аннотации, встроенные файлы и интерактивные действия не имеют значения для печати, поэтому инструменты предварительной проверки (Adobe Acrobat, Enfocus PitStop, callas pdfaPilot) отклоняют документы, содержащие их.
  • Запрещены типы аннотаций (отклоняются при любом соответствии PDF/XCompliance ∈ {X-1a, X-3, X-4}):
    • FileAttachment — печатные устройства не используют встроенные файлы.
    • Sound — мультимедиа не предназначено для печатных рабочих процессов.
    • Movie — аналогичная причина, связанная с мультимедиа.
    Теперь каждая точка входа (AddFileAttachmentAnnotation, AddSoundAnnotation, AddMovieAnnotation) вызывает диагностическое сообщение, соответствующее разделу спецификации, и значение PDF/XCompliance, когда вызывается в рамках любого профиля PDF/X.
  • Запрещены следующие типы действий (отклоняются при любом соблюдении стандарта PDF/X): Launch, JavaScript, SubmitForm, ImportData, Movie, Sound, ResetForm. Рабочие процессы подготовки к печати не должны запускать никакие внешние программы — PDF-файл должен обрабатываться только печатным оборудованием/RIP, а не выполняться. Функция AddLaunchLink теперь вызывает ошибку при любом профиле PDF/X (другие действия, которые HotPDF не предоставляет в качестве публичных API, автоматически обрабатываются).
  • Серия PDF/X теперь полностью реализована: v2.112 (опциональная поддержка + идентификация XMP + "Trapped /Name") + v2.113 (OutputIntent + ICC GTS_PDFX) + v2.114 (контроль прозрачности + принудительное применение PageBox) + v2.115 (запрет аннотаций/действий). Поддерживаются все три отраслевых стандарта (X-1a:2001, X-3:2002, X-4:2010). Пользователь по-прежнему создает контент для подготовки к печати на уровне страниц (правильные цветовые модели CMYK, внедрение шрифтов с помощью подмножества TTF версии v2.84, размеры TrimBox, соответствующие дизайну, BleedBox при необходимости), но все структурные проверки соответствия реализованы.
  • Win32 + Win64: чистая сборка; базовые версии v2.108 - v2.114 пересобраны без изменений. `smoke_pdfx_optin` расширен за счет 4 новых тестов отказа (TestRejectFileAttachmentAnnot, TestRejectSoundAnnot, TestRejectMovieAnnot, TestRejectLaunchAction) — каждый из них генерирует запрещенный тип в одном из трех профилей PDF/X и подтверждает корректный отказ. Теперь общий набор тестов охватывает 11 сценариев: 3 сценария успешной генерации + 8 сценариев отказа.
  • В этой группе были закрыты две параллельные серии с несколькими версиями: PAdES (ETSI EN 319 142, v2.109 - v2.111, 3 коммита, поддерживаются все варианты B-B / B-T / B-LT / B-LTA, а также автономная временная метка) и PDF/X (ISO 15930, v2.112 - v2.115, 4 коммита, реализованы все необходимые проверки структурного соответствия стандартам X-1a / X-3 / X-4 на стороне производителя).

2026-05-20 Version 2.114.0

  • PDF/X (ISO 15930) серия производителей, часть 3/4: реализована функция контроля прозрачности и принудительное применение PageBox в соответствии с ISO 15930-1:2001 / ISO 15930-3:2002 / ISO 15930-7:2010 + ISO 32000-1 §14.11.2. Эта часть охватывает два независимых ограничения, которые применяются к каждой странице; структура разделения соответствует схеме v2.103 PDF/A-1, определяющей функции прозрачности и отображения страниц.
  • Прозрачность (раздел 7.5): Функция RegisterExtGState отклоняет значения альфа-канала заливки меньше 1 (/ca), альфа-канала обводки меньше 1 (/CA) или режимы наложения, отличные от {Normal, Compatible}, если PDFXCompliance установлено в 'X-1a' или 'X-3'. PDF/X-1a (ISO 15930-1:2001) и PDF/X-3 (ISO 15930-3:2002) требуют базовую версию PDF 1.3, которая предшествует прозрачности в PDF 1.4. PDF/X-4 (ISO 15930-7:2010, базовая версия PDF 1.6) явно разрешает использование прозрачности, поэтому проверка не срабатывает при использовании X-4. Диагностическое сообщение объясняет причину и предлагает обновить версию до X-4, если требуется использование прозрачности.
  • В разделе "PageBox enforcement" (§14.11.2) добавлен новый метод `EnsurePDFXPageBoxes`, который проверяет каждую страницу и требует наличия хотя бы одного из параметров /TrimBox или /ArtBox. Использование только параметра MediaBox недостаточно, поскольку он представляет собой область дизайна, а не размеры готовой страницы, которые необходимо знать типографии. Если параметры PageBox отсутствуют, возникает ошибка, содержащая номер страницы (с отсчетом от 1), ссылку на соответствующий раздел спецификации и рекомендуемый способ вызова функции SetTrimBox. В конце процесса, функция `EnsurePDFXPageBoxes` автоматически вызывается после проверки `OutputIntent` в блоке `PDFXCompliance`.
  • Обычно, после установки параметров PDFXCompliance, Trapped и AddPDFXOutputIntent, для каждой страницы документа необходимо вызвать `CurrentPage.SetTrimBox(Left, Bottom, Right, Top)`, чтобы указать размеры готового продукта (например, 0 0 612 792 для формата US Letter или 0 0 595 842 для формата A4). Рекомендуется использовать BleedBox, но это не является обязательным.
  • Чистая сборка для Win32 и Win64; все базовые версии от v2.108 до v2.113 были пересобраны без изменений. `smoke_pdfx_optin` расширен следующим образом: добавлены положительные тесты для вызова `SetTrimBox` в каждом из трех профилей, реализован путь для отклонения отсутствия `TrimBox`, реализован путь для отклонения прозрачности X-1a (вызов `RegisterExtGState` с `ca=0.5` приводит к ошибке), реализован положительный путь для прозрачности X-4 (тот же вызов успешен и `ExtGState` зарегистрирован). Верификатор на Python проходит по каждому словарю `/Type /Page` и проверяет, что хотя бы один из элементов `/TrimBox` или `/ArtBox` присутствует для каждой страницы.
  • Остальная часть PDF/X: версия 2.115 завершает серию, удаляя запрещенные типы действий (JavaScript / Launch / SubmitForm / ImportData / Movie / Sound), запрещенные типы аннотаций (Movie / Sound / FileAttachment / Screen) и отключая поддержку AcroForm /XFA. Функции печати не должны использовать эти возможности; инструменты предварительной проверки для конечных пользователей отмечают их как критические ошибки.

2026-05-19 Version 2.113.0

  • PDF/X (ISO 15930) серия производителей, часть 2/4: принудительное применение профиля ICC и параметра OutputIntent в соответствии с 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. Каждый профиль PDF/X требует наличия хотя бы одной записи с типом /Type /OutputIntent и подтипом /S /GTS_PDFX, которая определяет целевые параметры печати и предоставляет поток профиля ICC для выходных данных. Типографии используют это для цветокоррекции PDF в соответствии с конкретной комбинацией печатного оборудования, бумаги и чернил.
  • Новая функция `AddPDFXOutputIntent(OutputConditionIdentifier, Info, ICCProfileStream, NumComponents, AlternateCS)` аналогична обертке PDF/A версии v2.102, но генерирует подтип GTS_PDFX вместо GTS_PDFA1. Она проверяет, что `ICCProfileStream` не является нулевым, а `OutputConditionIdentifier` не является пустым; вызывает `RegisterICCProfile` для встраивания профиля (автоматически обрабатывает соответствие цветового пространства /Alternate значению `NumComponents`) и `AddOutputIntent` для создания словаря `OutputIntent`.
  • Принудительное применение правил: когда параметр PDFXCompliance установлен, функция EnsurePDFXOutputIntent проверяет массив OutputIntents и требует наличия хотя бы одной записи с параметрами /S /GTS_PDFX + /DestOutputProfile. Если такая запись отсутствует, возникает ошибка с предложением зарегистрированного идентификатора (FOGRA39 для печатных листов, CGATS TR 001 SWOP для североамериканского рынка, Japan Color 2001 Coated для азиатских рынков).
  • Обычно процесс создания PDF/X выглядит следующим образом: 1) `Doc.PDFXCompliance := 'X-4'`, 2) `Doc.Trapped := 'False'`, 3) загрузка цветового профиля CMYK ICC (FOGRA39 / SWOP / и т.д.) в объект `TStream`, 4) `Doc.AddPDFXOutputIntent('FOGRA39 (ISO 12647-2:2004)', '', ICCStream, 4, 'DeviceCMYK')`, 5) создание содержимого, 6) `Doc.EndDoc` генерирует выходные параметры, связанные с массивом `/OutputIntents` в каталоге; инструменты предварительной проверки (Adobe Acrobat, Enfocus PitStop, callas pdfaPilot) проверяют правильность цветопередачи.
  • Win32 + Win64: чистая сборка; базовые версии v2.108 / v2.109 / v2.110 / v2.111 / v2.112 полностью пересобраны без изменений. `smoke_pdfx_optin` (изначально v2.112) расширен для: регистрации фиктивного ICC-профиля + добавления `AddPDFXOutputIntent` в каждый из трех генерируемых профилей (X-1a → FOGRA39 CMYK, X-3 → SWOP CMYK, X-4 → sRGB RGB) и добавления пути отказа, который проверяет, что отсутствие `OutputIntent` вызывает ошибку. Верификатор на Python расширен для обхода каждого словаря и проверки наличия записи `/Type /OutputIntent /S /GTS_PDFX` с параметром `/DestOutputProfile`.
  • Оставшиеся фрагменты PDF/X: в версии v2.114 добавлена проверка прозрачности (X-1a / X-3 отклоняют заполнение/обводку с альфа-каналом ExtGState и значения меньше 1 + BM, отличные от Normal; X-4 разрешает прозрачность) + принудительное применение PageBox (каждая страница должна иметь TrimBox или ArtBox в соответствии с §14.11.2); в версии v2.115 завершена серия, запрещены действия / annot / XFA (Movie / Sound / FileAttachment / Screen / JavaScript / Launch / SubmitForm / ImportData / XFA отклоняются, поскольку они не подходят для печатных рабочих процессов).

2026-05-19 Version 2.112.0

  • Начата серия инструментов для подготовки PDF-файлов к печати в соответствии со стандартом PDF/X (ISO 15930). PDF/X – это семейство стандартов ISO, предназначенное для передачи PDF-файлов, готовых к печати, коммерческим типографиям; профили X-1a (строгий CMYK + пантон), X-3 (управление цветом с использованием ICC) и X-4 (прозрачность PDF 1.6 + ICCN) – три наиболее распространенных в отрасли. Версия 2.112 – это часть 1 из 4: добавлена опциональная настройка и метаданные идентификации. Полный аудит и дорожная карта на 4 версии доступны по адресу .superpowers/specs/2026-05-19-pdfx-compliance-audit.md.
  • Добавлено свойство `PDFXCompliance: AnsiString` в классе THotPDF, которое принимает значения `''` (отключено, по умолчанию), `'X-1a'` (ISO 15930-1:2001), `'X-3'` (ISO 15930-3:2002) или `'X-4'` (ISO 15930-7:2010). Установка любого значения, отличного от пустого, автоматически включает все требования, которые HotPDF может выполнить структурно для указанного профиля.
  • Добавлено свойство `Trapped: AnsiString` (обязательно при соответствии стандарту PDFX), которое принимает значения `'True'`, `'False'` или `'Unknown'`. Семейство стандартов PDF/X требует наличия этой записи в DocInfo, чтобы типография знала, была ли PDF-документ уже обработан для трапирования или требует обработки в процессе подготовки к печати. Оно выводится в виде объекта PDF с ключом `/Name` (а не строки), в соответствии с ISO 32000-1 §14.11.6.1; например, `<< /Trapped /False >>`.
  • Обнаружение метаданных XMP: теперь пакет объявляет `xmlns:pdfx="http://ns.adobe.com/pdfx/1.3/"` с установленным значением ``, соответствующим спецификации (например, `PDF/X-1:2001`, `PDF/X-3:2002` или `PDF/X-4`), и (для X-1a + X-4) с установленным значением ``, равным полному названию профиля (`PDF/X-1a:2001` или `PDF/X-4:2010`). Программы Adobe Acrobat, Enfocus PitStop и callas pdfaPilot распознают этот документ как потенциальный PDF/X файл.
  • Проверка EndDoc: отклоняются неизвестные значения профиля, отклоняются пустые или нераспознанные значения Trapped, требуется поле "Title", автоматически повышается версия PDF до минимальной обязательной версии, указанной в профиле (X-1a/X-3 → PDF 1.3, X-4 → PDF 1.6). Шифрование и соответствие стандарту PDF/X являются несовместимыми – вызов EnableEncrypt (или `ActivateProtection := True`) приводит к ошибке с подробным описанием, объясняющим, что процессы, соответствующие стандарту PDF/X, должны проверять каждый объект без использования обработки паролей.
  • Вызывающая сторона по-прежнему отвечает за создание профиля ICC + OutputIntent + TrimBox/ArtBox + корректных цветовых пространств для допечатной подготовки + правильной встраивания шрифтов (и избегает прозрачности для X-1a/X-3) для обеспечения полного соответствия стандарту PDF/X. Версии v2.113 - v2.115 устраняют эти недостатки: v2.113 добавляет `AddPDFXOutputIntent` (обязательный профиль /GTS_PDFX), v2.114 добавляет фильтр прозрачности и принудительное применение PageBox, v2.115 завершает серию, добавляя запреты на действия, аннотации и XFA.
  • Win32 + Win64: чистая сборка; базовые версии v2.108 / v2.109 / v2.110 / v2.111 пересобраны без изменений. Новый тест smoke_pdfx_optin создает три PDF-файла (по одному для каждого профиля) и проверяет пространство имен XMP, а также GTS_PDFXVersion + GTS_PDFXConformance, а также DocInfo /Trapped /Name, а также сценарии обработки недействительных профилей, пустых значений Trapped, неизвестных значений Trapped и отклонения из-за конфликтов шифрования.
  • Заметки по серии PAdES: версии v2.109 / v2.110 / v2.111 охватывают сценарии использования B-B / B-T / B-LT / B-LTA, а также автономную временную метку. Версия v2.112, которая изначально планировалась (автономный PDF-файл только с временной меткой ETSI.RFC3161), фактически реализована неявно — функция `AddDocumentTimestampSignature` версии v2.111 работает с новым документом без внутренней подписи, поэтому серия PAdES считается завершенной, состоящей из 3 коммитов, а версия v2.112 перераспределяется для PDF/X. Поддерживаются все базовые профили ETSI EN 319 142-1.

2026-05-19 Version 2.111.0

  • Серия PAdES producer, часть 3/4: Поддержка цифровой подписи временной метки документа PAdES-B-LTA в соответствии с ISO 32000-1 §12.8.5 + ETSI EN 319 142-1 §5.7. Временная метка документа представляет собой вторую подпись, применяемую ПОСЛЕ завершения подписи с долгосрочной проверкой; она охватывает весь файл состояния долгосрочной проверки (исходная подпись + DSS) и подтверждает, что материалы долгосрочной проверки существовали в момент, зафиксированный нотариально. Это профиль архивирования, необходимый для соблюдения требований ЕС по долгосрочному хранению, превышающих срок действия исходного сертификата CA.
  • Добавлен новый вспомогательный метод `THPDFPage.AddDocumentTimestampSignature(FieldName, ContentsBytes)`. В отличие от обычной цифровой подписи PAdES, временная метка документа имеет:
    • Подтип `/ETSI.RFC3161` (токен временной метки RFC 3161, а не CAdES).
    • Область виджета, равная нулю (временная метка не имеет видимого представления — это чисто криптографические метаданные).
    • Отсутствуют поля `/Reason`, `/Location` и `/ContactName` (эти поля находятся в подписанных атрибутах TST, а не в словаре подписи).
    • Значение по умолчанию для поля `/Contents` — 16 КБ (вызывающий может передать меньшее значение, но не меньше 1 КБ; полная временная метка TST с цепочкой сертификатов обычно составляет 4-8 КБ).
  • Область действия параметра Producer заканчивается на уровне формата файла: помощник создает словарь-заполнитель с ключами /Type и /Sig, содержащий информацию о временной метке, а также поля /ByteRange и /Contents для последующей корректировки после создания файла с помощью PreparePDFForSigning и InsertSignatureHex. Вызывающая сторона получает фактические байты TST (Timestamped Signed Data) в соответствии со стандартом RFC 3161 от доверенного органа по выдаче временных меток (TSA, например, DigiCert / GlobalSign / FreeTSA через HTTP POST) и внедряет их. Типичный процесс архивирования PAdES-B-LTA включает в себя следующие этапы: 1) создание базовой подписи PAdES-B-LT (версия 2.109), 2) заполнение каталога /DSS цепочкой сертификатов и данными OCSP/CRL (версия 2.110), 3) сохранение как инкрементного обновления, 4) добавление поля временной метки документа поверх байтов состояния LT (версия 2.111), 5) запрос временной метки от TSA для указанного диапазона байтов, 6) внедрение байтов временной метки.
  • Win32 + Win64: чистая сборка; базовые версии v2.108 / v2.109 / v2.110 пересобраны без изменений. Новый модуль `smoke_pades_doctimestamp` создает поле `SigInner` в формате PAdES-B-LT, а также поле `DocTS` для временной метки документа, используя новый вспомогательный модуль. Проверка на Python убеждается, что внутренняя подпись имеет `/SubFilter /ETSI.CAdES.detached`, прямоугольник виджета временной метки имеет нулевую площадь, словарь `/V` для временной метки имеет `/SubFilter /ETSI.RFC3161` и не содержит ключей `/Reason`, `/Location`, `/ContactName`, а `/Contents` представляет собой заполнитель размером 16 КБ (32768 шестнадцатеричных символов).
  • Оставшаяся часть PAdES: версия 2.112 (опционально) добавляет автономные PDF-файлы с временной меткой ETSI.RFC3161 (без внутренней подписи CAdES — это просто контейнер для временной метки).

2026-05-19 Version 2.110.0

  • PAdES, серия продуктов, выпуск 2/4: Поддержка словаря Document Security Store (DSS) в соответствии с ISO 32000-2 §12.8.4.3 и ETSI EN 319 142-1 §5.6. PAdES-B-LT (и B-LTA) требуют, чтобы информация, связанная с проверкой, такая как цепочка сертификатов, ответы OCSP и списки отзыва сертификатов (CRLs), была встроена непосредственно в PDF-файл, чтобы подписи можно было проверять спустя долгое время после первоначальной подписи, без необходимости обращаться к внешним серверам PKI.
  • Добавлены новые функции в THotPDF:
    • `EnsurePAdESDSS` — создает каталог /DSS и его подсловарь /VRI, а также массивы /Certs, /OCSPs и /CRLs; последующие вызовы возвращают существующий словарь.
    • `AddPAdESDSSCertificate(CertDERBytes)` — добавляет закодированный в DER формат X.509 сертификат в качестве косвенного потока в /DSS /Certs; возвращает объект косвенного потока для использования в ссылках VRI.
    • `AddPAdESDSSOCSP(OCSPDERBytes)` — аналогично для базового ответа OCSP в /DSS /OCSPs.
    • `AddPAdESDSSCRL(CRLDERBytes)` — аналогично для списка отзыва сертификатов в /DSS /CRLs.
    • `AddPAdESDSSVRI(SigContentsHexSHA1, Certs, OCSPs, CRLs)` — создает запись VRI для каждой подписи, используя шестнадцатеричный SHA-1 в верхнем регистре байтов /Contents (форма ключа, требуемая спецификацией); каждая запись содержит массивы /Cert, /OCSP и /CRL, ссылающиеся на созданные выше косвенные потоки.
  • Область действия параметра "Producer" заканчивается на уровне формата файла. Вызывающая программа по-прежнему вычисляет SHA-1 для окончательного подписанного содержимого (/Contents) и предоставляет закодированные в DER-формате сертификаты / ответы OCSP / списки отзыва сертификатов (CRLs) из своих инструментов PKI. Типичный рабочий процесс: создается базовая подпись PAdES-B-T (версии v2.109), затем сертификаты / ответы OCSP / CRL добавляются в DSS для долгосрочной проверки, а затем добавляются записи VRI, связывающие информацию о проверке с конкретными подписями.
  • Win32 и Win64: чистая сборка; базовые версии v2.108 и v2.109 были пересобраны без изменений. Новый тест smoke_pades_dss создает поле цифровой подписи PAdES-B-LT, добавляет 2 сертификата + 1 OCSP + 1 CRL в DSS и добавляет запись VRI с тестовым шестнадцатеричным хешем. Верификатор на Python обходит структуру словаря DSS: ссылка на каталог /DSS, массивы /Certs, /OCSPs, /CRLs, подсчитывает элементы, проверяет соответствие ключей VRI, проверяет соответствие ссылок сертификатов/OCSP/CRL в записи VRI и массивам DSS верхнего уровня.
  • Оставшиеся фрагменты PAdES: v2.111 реализует цифровую подпись временной метки документа PAdES-B-LTA (второе поле Sig с SubFilter ETSI.RFC3161, охватывающее весь файл LT); v2.112 (опционально) добавляет автономные PDF-файлы, содержащие только временную метку.

2026-05-19 Version 2.109.0

  • Начата работа над генератором цифровых подписей PAdES (ETSI EN 319 142). Версия v2.109 добавляет высокоуровневый интерфейс к существующей инфраструктуре подписей ISO 32000-1 §12.8 (версия 2 вспомогательной функции AddSignedSignatureField), который жестко задает необходимый SubFilter и проверяет соответствие профилю. Полный аудит и дорожная карта на 4 версии архивированы по адресу .superpowers/specs/2026-05-19-pades-compliance-audit.md.
  • Добавлен новый вспомогательный метод `THPDFPage.AddPAdESSignatureField(FieldName, Rect, Profile, Reason, Location, ContactName, ContentsBytes, Flags)`. Параметр `Profile` позволяет выбрать базовый уровень ETSI EN 319 142-1: `'B-B'` (базовая CAdES, без временной метки), `'B-T'` (с доверенной временной меткой RFC 3161, минимальный уровень для юридического использования в ЕС), `'B-LT'` (с информацией DSS для долгосрочной проверки) или `'B-LTA'` (с цифровой подписью с временной меткой документа для архивирования). Все четыре варианта используют `SubFilter 'ETSI.CAdES.detached'`, а параметр `profile` изменяет диагностические данные и объем байтов `/Contents` по умолчанию. Другие строки параметра `profile` приводят к ошибке, так как не соответствуют перечислению ETSI.
  • Автоматически увеличивается объем памяти, выделяемый для содержимого: для PAdES-B-B + B-T по умолчанию используется 16 КБ (вызывающая сторона может указать меньшее значение; мы устанавливаем минимальный порог в 64 байта, унаследованный от версии v2.108). Для PAdES-B-LT минимальный объем памяти автоматически увеличивается до 20 КБ (включает данные CAdES, цепочку сертификатов и данные OCSP/CRL). Для PAdES-B-LTA минимальный объем памяти автоматически увеличивается до 24 КБ (включает B-LT и временную метку документа). Значения, указанные вызывающей стороной и превышающие установленные, принимаются без изменений; вспомогательный модуль только устанавливает минимальный порог.
  • Область применения: этот компонент создает словарь-заполнитель с ключами `/Type` и `/Sig`, а также ключами `/SubFilter /ETSI.CAdES.detached`, `/Reason`, `/Location`, `/ContactName` и `/M` (дата подписания), а также метками `/ByteRange` и `/Contents` для последующей корректировки после создания файла с помощью `PreparePDFForSigning` и `InsertSignatureHex`. Фактические байты CMS/CAdES, получение временной метки в соответствии с RFC 3161, сбор OCSP/CRL и создание словаря DSS остаются ответственностью вызывающей стороны — для этого требуется внешняя криптографическая библиотека (например, OpenSSL, Bouncy Castle, Windows CAPI), которая выходит за рамки области применения создателя PDF-файлов.
  • Чистая сборка для Win32 и Win64. Новый тест `smoke_pades_signature` создает четыре поля цифровой подписи PAdES (B-B / B-T / B-LT / B-LTA) и проверяет, что некорректные значения профиля вызывают ошибку. Тестировщик Python проверяет, что для `AcroForm /SigFlags` установлено значение 3, каждый виджет имеет атрибуты `/FT /Sig` и непрямую ссылку на словарь `/Type /Sig` с атрибутом `/SubFilter /ETSI.CAdES.detached`, а длина шестнадцатеричного представления в поле `/Contents` соответствует ожидаемому размеру (автоматически увеличивается).
  • В планах по дальнейшему развитию PAdES: в версии v2.110 добавлена функция построения словаря /DSS (хранилища безопасности документов) для PAdES-B-LT, включающая информацию о цепочке сертификатов и OCSP/CRL; в версии v2.111 добавлено отдельное поле для временной подписи документа, предназначенное для архивации PAdES-B-LTA; в версии v2.112 (опционально) добавлена поддержка PDF-файлов с временными метками, соответствующих стандарту ETSI.RFC3161.

2026-05-19 Version 2.108.0

2026-05-19 Version 2.107.0

2026-05-19 Version 2.106.0

  • PDF/A-2 + PDF/A-3: реализована поддержка разделов 2/4, охватывающих PDF/A-2 §6.3.1 + §6.5.1 (и идентичные разделы PDF/A-3 §6.3.1 + §6.5.1). В версии v2.104, функции запрета аннотаций и действий, которые активируются при наличии заполненного поля PDFACompliance, продолжают работать без изменений в PDF/A-2/3. Версия v2.106 подтверждает это поведение, обновляет диагностические сообщения, чтобы они ссылались на унифицированные разделы спецификации для всех версий PDF/A, и документирует дополнительные запрещенные типы, введенные в PDF/A-2, которые HotPDF удовлетворяет естественным образом (без отдельного пути реализации).
  • Матрица запрещенных действий: PDF/A-1 запрещает 6 действий (запуск, звук, видео, сброс формы, импорт данных, JavaScript). PDF/A-2 + PDF/A-3 расширяют этот список до 13, добавляя действия "скрыть", "установить состояние OCG", "рендеринг", "трансформация", "переход к 3D-виду", а также устаревшие подтипы "no-op". Функция AddLaunchLink продолжает работать; в THotPDF нет общедоступной функции, которая бы вызывала остальные 12 запрещенных действий, поэтому они автоматически удовлетворяются.
  • Запрещенные типы аннотаций: PDF/A-1 запрещает FileAttachment, Sound и Movie. PDF/A-2 / PDF/A-3 отменяют запрет на FileAttachment (снято в версии v2.105), но добавляют 3D и Screen в список запрещенных. Функции AddSoundAnnotation и AddMovieAnnotation по-прежнему вызывают ошибки во всех версиях PDF/A; в HotPDF нет возможности создания объектов 3D / Screen, поэтому эти ограничения автоматически соблюдаются.
  • Обновление диагностических сообщений: теперь все три функции v2.104 (AddSoundAnnotation, AddMovieAnnotation, AddLaunchLink) ссылаются на соответствующие разделы спецификации в своих сообщениях об ошибках (например, "PDF/A-1 §6.5.2 / PDF/A-2 §6.3.1 / PDF/A-3 §6.3.1"), чтобы разработчики могли видеть единое ограничение. Сообщение AddLaunchLink также перечисляет расширенный набор запрещенных действий для PDF/A-2/3.
  • Win32 + Win64: чистая сборка. Новый тестовый набор smoke_pdfa2_annot_action проверяет все три условия для всех шести уровней PDF/A-2/3 (2B, 2U, 2A, 3B, 3U, 3A); каждый вызов проверяет ожидаемое исключение с диагностикой, указанной в разделах §6.3.1 / §6.5.1. Предыдущие базовые тесты для PDF/A-1 (smoke_pdfa1_compliance / smoke_pdfa1_forbidden / smoke_pdfa1_annot_action) и сборка v2.105 smoke_pdfa2_compliance были пересобраны без изменений.
  • Оставшиеся фрагменты реализации стандарта PDF/A-2/3: версия 2.107 обеспечивает соответствие требованиям ISO 19005-2 §6.1.13 (ограничения для целочисленных/вещественных значений/строк/имен, вложенность q/Q, цветовые компоненты DeviceN, CID, границы страниц) + §6.4.2 XFA + §6.2.11 строгий контроль типов 3 / .notdef; версия 2.108 реализует поддержку PDF/A-3 Приложения E, включающего связанные файлы (гибридные контейнеры PDF с произвольными встроенными типами файлов).

2026-05-19 Version 2.105.0

  • Начата серия из четырех версий, обеспечивающих соответствие стандартам PDF/A-2 (ISO 19005-2:2011) и PDF/A-3 (ISO 19005-3:2012). Аудит и дорожная карта архивированы по адресу .superpowers/specs/2026-05-19-pdfa2-pdfa3-compliance-audit.md. Версия v2.105 включает опциональный слой, расширения пространства имен XMP pdfaid, автоматическое повышение базовой версии PDF до 1.7 и частичное ослабление строгих ограничений PDF/A-1, которые явно разрешены спецификациями PDF/A-2 и PDF/A-3.
  • Свойство PDFACompliance теперь принимает шесть новых значений, в дополнение к существующим '' / 'A' / 'B': '2A' / '2B' / '2U' (уровни A / B / U стандарта PDF/A-2) и '3A' / '3B' / '3U' (уровни A / B / U стандарта PDF/A-3). Уровень U – это новый уровень "только сохранение Unicode", представленный в стандарте PDF/A-2 (текст, видимый и извлекаемый с помощью Unicode, без требования использования "отмеченного PDF").
  • В `BuildXMPPacket` внесены изменения: элемент `` теперь отражает проаналированный номер части (1 / 2 / 3), а `` отражает проаналированный уровень (A / B / U). Такие валидаторы, как veraPDF, определяют часть документа PDF/A на основе этой пары. В соответствии с ISO 19005-2 §6.6.4 + ISO 19005-3 §6.6.4 Таблица 8.
  • Автоматическое обновление: PDFACompliance '2*' / '3*' автоматически повышает версию документа до PDF 1.7, поскольку PDF/A-2 и PDF/A-3 основаны на ISO 32000-1 (PDF 1.7). PDF/A-1 остается привязанным к PDF 1.4.
  • v2.103: Ограничения на прозрачность ослаблены: теперь функция RegisterExtGState выдает ошибку только в том случае, если используется прозрачный альфа-канал или режим смешивания, отличный от Normal, при строгом соблюдении стандарта PDFACompliance (PDF/A-1, т.е. 'A' или 'B'). Стандарты PDF/A-2 и PDF/A-3 §6.4 явно разрешают использование прозрачности (с отдельными требованиями, такими как наличие OutputIntent и полные имена режимов смешивания, определенные в PDF 1.4), поэтому при PDFACompliance со значениями '2*' или '3*' вызов функции проходит без ошибок.
  • v2.104: Ограничение для FileAttachment снято: функция AddFileAttachmentAnnotation теперь вызывает исключение только в строгом режиме PDF/A-1. В соответствии с PDF/A-2 §6.3.1, запрещены только типы аннотаций 3D / звук / экран / видео; FileAttachment разрешен и является основой гибридного рабочего процесса Annex E Associated Files в PDF/A-3. Остальные ограничения для аннотаций/действий (аннотации звука и видео; действие Launch) по-прежнему действуют во всех версиях PDF/A в соответствии с общими запретами, указанными в §6.3.1 и §6.5.1.
  • Новые вспомогательные методы THotPDF PDFAPart, PDFAConformanceLevel, IsPDFA1Strict и IsPDFA2OrLater упрощают выбор значений. Существующие функции PDF/A версий v2.101-104 теперь используют эти вспомогательные методы для более чистого кода и более понятных сообщений об ошибках, которые предлагают переход на PDF/A-2 или PDF/A-3 при необходимости.
  • Win32 и Win64: чистая сборка; базовые версии v2.101-104 (тесты соответствия PDF/A-1 / запрещенные элементы PDF/A-1 / действия аннотаций PDF/A-1) пересобраны без изменений. Новый тест smoke_pdfa2_compliance создает четыре PDF-файла (уровни 2B / 2U / 2A / 3U), проверяет функцию прозрачности v2.103 и функцию прикрепления файлов v2.104, а также включает два пути проверки (недопустимый уровень '4Q' отклонен; механизм проверки прозрачности PDF/A-1 по-прежнему работает). Верификатор на Python проверяет соответствие XMP pdfaid:part для каждого уровня, а уровень 2A имеет наследование тегов PDF.
  • Оставшиеся фрагменты реализации стандартов PDF/A-2/3: v2.106 расширяет набор запрещенных действий с 6 до 13 (добавлены Hide, SetOCGState, Rendition, Trans, GoTo3DView; устаревшие действия и недействия); v2.107 обеспечивает соблюдение ограничений реализации, указанных в ISO 19005-2 §6.1.13, а также применяет ограничения для XFA; v2.108 реализует поддержку связанных файлов в соответствии с приложением E стандарта PDF/A-3 (гибридные контейнерные PDF-файлы).

2026-05-19 Version 2.104.0

  • PDF/A-1: серия исправлений для производителя завершена (часть 4/4): исправлены запрещенные типы аннотаций (§6.5.2, такие как FileAttachment, Sound, Movie) и подтип действия запуска (§6.6.1). С выпуском версии v2.104 закрыты все 17 проблем, выявленных в ходе аудита соответствия PDF/A-1 от 2026-05-19 (.superpowers/specs/2026-05-19-pdfa1-compliance-audit.md): это включает в себя четыре основных пункта (§5, §6.7.11 – идентификация, §6.1.3 – запрет шифрования, §6.2.2 – OutputIntent, §6.4 – прозрачность), а также различные блокировки запрещенных функций.
  • §6.5.2 запрещенные типы аннотаций: `AddFileAttachmentAnnotation`, `AddSoundAnnotation` и `AddMovieAnnotation` теперь вызывают исключение в режиме `PDFACompliance` с указанием конкретного раздела спецификации. Согласно спецификации, "типы аннотаций FileAttachment, Sound и Movie не должны использоваться" для предотвращения зависимостей от внешнего контента и мультимедиа в архивных файлах.
  • §6.6.1 Действие запуска: Теперь функция `AddLaunchLink` вызывает исключение в режиме `PDFACompliance`, при этом выдается диагностическое сообщение, указывающее целевой объект запуска. Согласно спецификации, "действия запуска, воспроизведения звука, воспроизведения видео, сброса формы, импорта данных и JavaScript не допускаются". Остальные пять запрещенных типов действий (воспроизведение звука/видео/сброс формы/импорт данных/JavaScript) не имеют общедоступного интерфейса в `HotPDF`, который бы их генерировал, поэтому они автоматически удовлетворяют требованиям без явных ограничений.
  • PDFUACompliance и PDFACompliance теперь работают корректно во всех четырех вариантах PDF/A. Эти две опции работают совместно: уровень A наследует автоматическую активацию PDFUACompliance для тегированных PDF-файлов; оба варианта применяют свои собственные, специфичные для каждого стандарта, ограничения (для PDF/UA: "Suspects/Tabs/Lang"; для PDF/A: "Encrypt/Transparency/Annot/Action") без какого-либо взаимодействия.
  • Краткое описание закрытых задач: все требования к формату файла §6, которые HotPDF может удовлетворить на стороне производителя для соответствия стандарту PDF/A-1, теперь закрыты. Обязанности вызывающей стороны, которые остаются (пункты §6.1.5, эквивалентность Info-XMP, §6.2.3.3, соответствие цветового пространства и OutputIntent, §6.3, особенности шрифтов, где работа по соответствию PDF/UA-1 в версиях v2.74-v2.86 уже была выполнена), соответствуют аналогичным обязанностям вызывающей стороны в стандарте PDF/UA-1.
  • Чистая сборка для Win32 и Win64; v2.103 smoke_pdfa1_forbidden успешно перекомпилирован. Новый тест smoke smoke_pdfa1_annot_action проверяет все четыре ветвления (AddFileAttachmentAnnotation, AddSoundAnnotation, AddMovieAnnotation, AddLaunchLink) в разделе PDFACompliance и проверяет, что каждый вызов приводит к ошибке с диагностикой, указанной в §6.5.2 или §6.6.1.
  • Поверхность генератора PDF/A-1 теперь полностью закрыта для аудита. Будущие расширения PDF/A-2 (согласно ISO 19005-2:2011, основано на PDF 1.7, поддерживает прозрачность и слои) и PDF/A-3 (согласно ISO 19005-3:2012, поддерживает встроенные файлы для гибридных рабочих процессов) остаются потенциальными кандидатами для реализации в будущем, в зависимости от запросов пользователей.

2026-05-19 Version 2.103.0

  • PDF/A-1, серия производителей, часть 3/4: исправлены разделы §6.4 "Прозрачность" (КРИТИЧЕСКАЯ проблема #15) и §6.2.8 "Функция преобразования /TR в ExtGState" (проблема #14). Два раздела §6, связанные с существующими путями работы HotPDF, автоматически удовлетворяются без изменений в коде: §6.1.10 "Фильтр LZW" (HotPDF использует только FlateDecode в своем пути записи) и §6.2.4 "Изображение /Interpolate" (HotPDF никогда не использует /Interpolate). Это теперь задокументировано как автоматическое в отчете аудита.
  • §6.4 Прозрачность запрещает использование значений альфа, отличных от 1.0, и режимов смешивания, отличных от Normal/Compatible. Функция RegisterExtGState теперь работает с учетом соответствия стандарту PDFA: значение альфа заливки меньше 1 вызывает ошибку (PDF/A-1 требует /ca = 1.0); значение альфа обводки меньше 1 вызывает ошибку (/CA = 1.0); режим смешивания, отличный от `Normal` или `Compatible`, вызывает ошибку. Все три диагностические сообщения указывают раздел спецификации и недопустимое значение. Значения по умолчанию для ExtGState (без ключей альфа и без режима смешивания) и явно разрешенные значения (значения альфа равные 1.0, режимы смешивания Normal/Compatible) остаются неизменными.
  • §6.2.8 ExtGState запрещает использование ключа функции преобразования /TR (устарело; PDF/A-1 допускает только /TR2 со значением /Default, и даже это лучше избегать). Функция RegisterTransferFunctionState теперь вызывает исключение PDFACompliance с четким диагностическим сообщением. Пользователи, которым требуются функции преобразования для рабочих процессов PDF/X, по-прежнему могут использовать вспомогательную функцию вне режима PDFACompliance.
  • §6.1.10 LZW + §6.2.4 Interpolate: документация указывает, что это требование автоматически удовлетворяется существующими механизмами HotPDF (только кодировщик FlateDecode, без генерации параметра "/Interpolate"). Изменения в коде не требуются; это отмечено в комментариях к отчету аудита, чтобы будущие разработчики не повторили эту ошибку.
  • Win32 + Win64: чистая сборка; v2.102 smoke_pdfa1_compliance успешно перекомпилирован. Новый тест smoke smoke_pdfa1_forbidden проверяет все три защищенных пути (ca<1, CA<1, BM=Multiply, регистрация /TR), а также подтверждает, что разрешенные пути (ca=1.0, CA=1.0, BM=Normal/Compatible, без альфа-канала) по-прежнему проходят. Отсутствует верификатор — сам тест smoke проверяет с помощью try/except, что каждый защищенный вызов вызывает исключение.
  • Оставшаяся часть кода, отвечающая за соответствие стандарту PDF/A-1: в версии v2.104 исправлены запрещенные типы аннотаций (FileAttachment, Sound, Movie) в соответствии с разделом §6.5.2, а также правила для аннотаций /F /AP в соответствии с разделом §6.5.3, и запрещенные типы действий (Launch, Sound, Movie, ResetForm, ImportData, JavaScript) в соответствии с разделом §6.9. Также исправлены поля формы /A /AA и добавлено свойство /NeedAppearances. После внедрения версии v2.104, функциональность, связанная с соответствием стандарту PDF/A-1, будет полностью завершена и протестирована.

2026-05-19 Version 2.102.0

  • PDF/A-1 (ISO 19005-1:2005) producer series, часть 2/4: исправлена проблема с отсутствием ICC-профиля в разделе §6.2.2 OutputIntent. Новый высокоуровневый помощник `AddPDFAOutputIntent(OutputConditionIdentifier, Info, ICCProfileStream, NumComponents, AlternateCS)` объединяет вызов `v2.51 RegisterICCProfile` и `AddOutputIntent('GTS_PDFA1', ...)` в один. Для соответствия стандарту PDF/A-1 требуется наличие записи `/Type /OutputIntent /S /GTS_PDFA1` с корректным ICC-потоком `/DestOutputProfile` — без этого файлы не смогут точно воспроизводить цвета на разных платформах.
  • Внесены изменения в механизм `PDFACompliance`, добавлена проверка `EnsurePDFAOutputIntent`: выполняется обход списка зарегистрированных `OutputIntent`, ищется хотя бы одна запись с `/S /GTS_PDFA1` и `/DestOutputProfile`. Если такая запись отсутствует, выводится информативное сообщение об ошибке, указывающее на соответствующий раздел спецификации и предлагающее пользователям использовать `AddPDFAOutputIntent`. В соответствии с §6.2.2 + Приложение A.
  • Обычно, для архивирования: передается поток ICC-профиля sRGB IEC61966-2.1 для PDF/A, ориентированного на экран, FOGRA39 / GRACoL для печати, или соответствующий зарегистрированный CMYK-профиль для подготовки к печати. `NumComponents` должен быть равен 1 (Gray), 3 (RGB / Lab) или 4 (CMYK) в соответствии с таблицей 66 раздела 8.6.5.5 стандарта PDF 1.7; вспомогательный модуль передает проверку в функцию `RegisterICCProfile`.
  • Помощник проверяет: пустой OutputConditionIdentifier вызывает ошибку (в соответствии с разделом 6.2.2, идентификатор обязателен); ICCProfileStream со значением nil вызывает ошибку (DestOutputProfile является обязательным). Функция не возвращает значение — OutputIntent автоматически регистрируется в FOutputIntents и предоставляется через существующий механизм сериализации Catalog /OutputIntents.
  • Win32 и Win64: чистая сборка; `v2.101 smoke_pdfa1_compliance` обновлен для вызова `AddPDFAOutputIntent` (с использованием фиктивного ICC-профиля размером 192 байта; реальные вызывающие функции используют настоящий двоичный ICC-профиль). Новый четвертый сценарий проверки утверждает, что отсутствие `OutputIntent` в разделе `PDFACompliance` вызывает диагностическое сообщение §6.2.2. Верификатор на Python расширен для проверки массива `Catalog /OutputIntents`, он перебирает записи, находя `/S /GTS_PDFA1` с непрямой ссылкой `/DestOutputProfile`.
  • Оставшиеся фрагменты кода для соответствия стандарту PDF/A-1: v2.103 исправляет ошибки #15 (прозрачность, CRITICAL), #5 (фильтр LZW), #10 (интерполяция изображений) и #14 (ExtGState /TR); v2.104 исправляет ошибки #16 (вложения файлов/звук/видео в аннотациях), #17 (правила для аннотаций /F /AP), #18 (действия Launch/Sound/Movie/ResetForm/ImportData/JavaScript) и #20 (поля формы /A /AA и /NeedAppearances).

2026-05-19 Version 2.101.0

  • Начата серия из четырех версий, обеспечивающих соответствие стандарту PDF/A-1 (ISO 19005-1:2005) на стороне производителя, с возможностью включения этой функции. Полный отчет об аудите, содержащий 17 пунктов, находится в архиве по адресу `.superpowers/specs/2026-05-19-pdfa1-compliance-audit.md`; версия v2.101 содержит основные компоненты (свойство PDFACompliance, идентификация XMP pdfaid, строгие требования к заголовку/языку, защита от конфликтов шифрования). Версии v2.102 - v2.104 устраняют оставшиеся проблемы, связанные с управлением цветом, прозрачностью, шрифтами и аннотациями/действиями.
  • Новое свойство `PDFACompliance: AnsiString` принимает значения '' (отключено, по умолчанию), 'A' (уровень A: визуальное отображение + помеченный PDF + доступность) или 'B' (уровень B: только визуальное сохранение). Недопустимые значения вызывают ошибку в конце документа. Соответствует уровням соответствия ISO 19005-1:2005 §5.
  • Установка значения PDFACompliance в 'A' автоматически включает PDFUACompliance (уровень A наследует требования к тегированию из раздела 6.8, которые соответствуют требованиям к логической структуре из раздела 7 стандарта PDF/UA-1). Оба параметра могут быть объединены без конфликтов; слой v2.94 PDF/UA-1, отвечающий за язык, заголовок и подозрительные элементы, накладывается на защитные механизмы v2.101 PDF/A.
  • Установка любого из этих уровней автоматически включает FEnableXMPMetadata, что позволяет документу содержать необходимый поток метаданных XMP (/Metadata). В соответствии с разделом §6.7.2, метаданные в каталоге являются обязательными.
  • Расширен функционал BuildXMPPacket: если значение PDFACompliance не пустое, пакет XMP объявляет `xmlns:pdfaid="http://www.aiim.org/pdfa/ns/id/"` и добавляет `1` и `A` (или `B`). Такие валидаторы, как veraPDF, полагаются на эту точную комбинацию для классификации документа как кандидата на соответствие стандартам PDF/A-1A или 1B. В соответствии с §6.7.11 Таблица 6 схемы идентификации PDF/A.
  • Заголовок / Строгость языка: Если включена функция PDFACompliance, а Doc.Title пуст, возникает ошибка (PDF/A-1 §6.7.3 требует наличия dc:title в XMP, эквивалентного Info /Title). Строгость языка соответствует поведению v2.94 PDFUACompliance (§6.8.4 для уровня A), поэтому авторы должны выбирать реальный тег BCP-47 вместо автоматической подстановки "en".
  • Защита от конфликтов шифрования: в соответствии с разделом 6.1.3, раздел трейлера файла не должен содержать "/Encrypt". Функция EnableEncrypt (внутренняя функция, которая вызывается при установке параметров OwnerPassword/UserPassword/Protection) теперь выдает четкое диагностическое сообщение, если PDFACompliance не является пустым. Функция EndDoc обнаруживает конфликт тем же путем, чтобы вызывающий код видел ошибку до сериализации.
  • В обязанности вызывающей стороны по-прежнему входит: создание корректного выходного файла PDF/A-1 с профилем ICC (исправление, внесенное в версии v2.102), избежание использования прозрачности (v2.103), предотвращение использования запрещенных типов аннотаций/действий (v2.104) и создание реальной семантической структуры для уровня A (что реализовано с помощью вспомогательных функций для тегированных PDF-файлов в версиях v2.96-v2.99).
  • Win32 + Win64: чистая сборка; v2.100: базовый сборка smoke_pdfua_link_contents успешно перекомпилирована. Новый тест smoke smoke_pdfa1_compliance создает файлы PDF уровней A и B, а также проверяет три пути валидации (недопустимый уровень Z, пустое поле Title, конфликт шифрования и соответствия PDFA). Python-тест проверяет наличие xmlns:pdfaid + pdfaid:part=1 + соответствующих значений pdfaid:conformance, dc:title, а также для уровня A дополнительно проверяются поля /MarkInfo /Marked true, Catalog /Lang и /StructTreeRoot, а также xmlns:pdfuaid (автоматическое наследование).

2026-05-19 Version 2.100.0

  • Устранена оставшаяся проблема с охватом аннотаций ссылок /Contents в соответствии с PDF/UA-1 §7.18.5, выявленная в ходе аудита от 2026-05-19. В версии v2.95 добавлено описание для функции AddURILink; в версии v2.100 аналогичная поддержка альтернативного описания реализована для оставшихся трех точек входа для ссылок: AddGoToLink (переход внутри документа), AddGoToRLink (переход между файлами) и AddLaunchLink (запуск внешнего файла).
  • Каждый вспомогательный элемент получает необязательный финальный параметр `const Description: AnsiString = ''`. Если этот параметр не пуст, словарь аннотации содержит запись `/Contents (Description)`; в режиме `PDFUACompliance`, если Description пуст, возникает ошибка с четким диагностическим сообщением, указывающим на проблемный целевой элемент ссылки, чтобы предотвратить незаметное прохождение отсутствующего альтернативного описания. Значение по умолчанию — пустая строка, что обеспечивает обратную совместимость вне режима PDFUACompliance.
  • В соответствии с PDF/UA-1 §7.18.5, строго: "Ссылки должны содержать альтернативное описание через свой ключ Contents, как описано в ISO 32000-1:2008, 14.9.3." Это требование распространяется на все типы аннотаций ссылок, а не только на URI-ссылки; теперь вспомогательные сигнатуры обеспечивают единообразное применение этого правила.
  • Типичный рабочий процесс: `Page.AddGoToLink(R, 1, 700, 'Перейти к странице 2: Методология'); Page.AddGoToRLink(R, 'companion.pdf', 0, -1, false, 'Открыть сопроводительный документ для получения полных таблиц данных'); Page.AddLaunchLink(R, 'readme.txt', false, 'Открыть README в текстовом редакторе по умолчанию');`
  • Win32 + Win64: чистая сборка; v2.99: базовая сборка smoke_pdfua_figure успешно перекомпилирована. Новый тест smoke smoke_pdfua_link_contents создает документ из 2 страниц с тремя аннотациями Link на странице 0 (переход на страницу 1, переход с повтором на 'companion.pdf', запуск 'readme.txt') и также проверяет обработку исключения PDFUACompliance для пустых значений Description для всех трех аннотаций. Проверка на Python подтверждает, что каждая аннотация Link содержит /Subtype /Link, соответствующий тип действия /S /GoTo (или /GoToR или /Launch) и значение /Contents, соответствующее предоставленному значению Description.
  • В версии v2.100 все четыре точки входа для аннотаций ссылок соответствуют разделу §7.18.5. Вместе с закрытием аудита в версии v2.94 (Suspects, Tabs, Lang), v2.95 (URI Contents, Bit 10, ID) и серией инструментов для работы с семантикой тегированных PDF-файлов в версиях v2.96-v2.99 (Heading, List, Table, Figure), функциональность PDF/UA-1 в HotPDF полностью прошла аудит как на уровне строгого соответствия спецификации, так и на уровне удобного API.

2026-05-19 Version 2.99.0

  • Добавлены `BeginTaggedFigure(Parent, AltText, BBox): FigureElem` и `EndTaggedFigure` в качестве четвертого и последнего элемента серии семантических помощников для PDF/UA-1 §7.3 (Графика). Эти элементы позволяют заключать операции отрисовки, предоставляемые вызывающей стороной (изображения XObject, векторные пути, заполненные прямоугольники), внутри элемента структуры Figure с обязательным атрибутом /Alt и необязательным атрибутом /BBox.
  • `/Alt` является обязательным атрибутом (отсутствует значение по умолчанию). В соответствии с PDF/UA-1 §7.3, действует строгое требование: "Теги для изображений должны включать альтернативное представление или текст, заменяющий изображение, который описывает его содержимое". Пустое значение `AltText` вызывает ошибку с четким сообщением, указывающим вызывающим сторонам на перегрузку функции `AddStructureElement` с 6 аргументами, если `/ActualText` (а не `/Alt`) является подходящим механизмом для предоставления альтернативного текста.
  • Опциональный атрибут BBox представляет собой массив из 4 значений [llx, lly, urx, ury], описывающий ограничивающий прямоугольник фигуры в пользовательском пространстве по умолчанию, и добавляется как /A << /O /Layout /BBox [...] >> в соответствии с ISO 32000-1 14.8.5.4.5. Для пропуска атрибута BBox передайте пустой массив. Неправильная длина BBox (1/2/3/5+ элементов) приведет к ошибке, при этом спецификация для прямоугольной разметки используется в качестве ориентира.
  • Обычный рабочий процесс: `Fig := Doc.BeginTaggedFigure(Root, 'Логотип компании: стрелка, указывающая вправо', [72, 600, 200, 720]); ... отрисовка содержимого фигуры ... Doc.EndTaggedFigure;` Объект Figure участвует в той же структуре MCID / ParentTree, что и другие пути v2.90 BeginTaggedContent, но атрибуты /Alt и /BBox добавляются автоматически.
  • Это устраняет проблему, связанную с разделом 7.3 стандарта PDF/UA-1, касающуюся ответственности вызывающего кода, как указано в отчете аудита. Серия вспомогательных функций для семантики тегированных PDF теперь охватывает все четыре основных типа структур: §7.4 (заголовок, v2.96), §7.6 (список, v2.97), §7.5 (таблица, v2.98), §7.3 (рисунок, v2.99). Вместе с исправлениями "оберточного" уровня в версиях v2.94 и v2.95, функциональность HotPDF, связанная со стандартом PDF/UA-1, теперь полностью соответствует спецификации на уровне API и удобна в использовании.
  • Win32 + Win64: чистая сборка; базовый сборка smoke_pdfua_table успешно перекомпилирован. Новый тест smoke_pdfua_figure создает два элемента структуры Figure (один с /Alt + /BBox, один только с /Alt) и также проверяет сценарии с отсутствующим текстом для /Alt и некорректными значениями для /BBox. Python-верификатор проверяет оба типа Figure /S, содержимое текста /Alt и значения массива BBox, которые должны быть [72, 600, 200, 720].

2026-05-19 Version 2.98.0

  • Добавлены четыре вспомогательных функции для тегированных таблиц в соответствии с PDF/UA-1 §7.5 (Таблицы), как часть серии вспомогательных функций для семантической разметки PDF. `BeginTaggedTable(Parent): TableElem` создает контейнер структуры таблицы; `AddTaggedTableRow(Table): TRElem` добавляет строку таблицы (TR); `EmitTaggedTableHeader(TR, X, Y, Text, Scope): THElem` создает ячейку заголовка (TH) с обязательным атрибутом /Scope; `EmitTaggedTableCell(TR, X, Y, Text): TDElem` создает ячейку данных (TD). Все пять типов тегов (Table, TR, TH, TD и объект атрибута) соответствуют спецификации.
  • Атрибут /Scope (ISO 32000-1 14.8.5.7 Таблица 350) является обязательным для элемента helper (без значения по умолчанию) и может принимать допустимые значения `Row`, `Col` или `Both`. Недопустимые строки атрибута Scope приводят к ошибке, как указано в спецификации. PDF/UA-1 §7.5: "Элементы структуры типа TH должны иметь атрибут Scope. Если структуру таблицы невозможно определить с помощью заголовков и идентификаторов, то элементы структуры типа TH должны иметь атрибут Scope." Явное указание атрибута Scope в сигнатуре элемента helper предотвращает возникновение ошибки, связанной с отсутствием атрибута Scope.
  • В данном обновлении, сериализация области (scope) соответствует стандартной форме атрибутов: `/A << /O /Table /Scope / >>` (согласно ISO 32000-1 14.7.5.3 Class Map), что позволяет программам-читателям интерпретировать это как атрибут пространства имен "Table". Это соответствует той же структуре, что и атрибут списка `/A << /O /List /ListNumbering ... >>`, представленный в версии 2.97.
  • Таблицы и элементы `TR` являются чисто структурными контейнерами (без помеченного контента на странице), но элементы `TH` и `TD` содержат видимый текст, поэтому оба проходят через `BeginTaggedContent + TextOut + EndTaggedContent`. Каждый элемент `TH` и `TD` получает свой собственный MCID, оператор `BDC` в потоке содержимого страницы и запись `ParentTree`. Вспомогательная функция возвращает элемент структуры `StructElem` для вызывающих, которым требуется добавить дополнительные атрибуты (например, список `/Headers` для сложных таблиц, `/RowSpan`, `/ColSpan`).
  • Обычный рабочий процесс: `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')); ...` Заменяет многоступенчатую структуру версии 2.90, а также последовательность BDC/EMC для каждой ячейки.
  • Это закрывает раздел PDF/UA-1 §7.5, касающийся ответственности вызывающей стороны, согласно отчету аудита. Серия вспомогательных функций для семантики тегированных PDF теперь охватывает разделы §7.4 (Заголовок, v2.96), §7.6 (Список, v2.97) и §7.5 (Таблица, v2.98). Оставшаяся часть (v2.99+): Вспомогательная функция для раздела §7.3, включающая /BBox, /Alt и блок отрисовки, предоставляемый вызывающей стороной.
  • Win32 и Win64: чистая сборка; v2.97: базовая сборка smoke_pdfua_list успешно перекомпилирована. Новая сборка smoke smoke_pdfua_table создает таблицу из 3 строк (1 заголовок + 2 данных) с 3 ячейками TH (Scope=Col) + 6 ячейками TD + проверяет исключение для недопустимого Scope. Верификатор Python проверяет полную структуру Table > TR > TH/TD с параметрами /Scope /Col для каждой ячейки TH.

2026-05-19 Version 2.97.0

  • Добавлены два помощника для списков PDF/UA-1 §7.6 в качестве второй части серии семантических помощников для тегированных PDF-файлов: `BeginTaggedList(Parent, NumberingStyle): ListElem` создает элемент структуры L с атрибутом объекта `/A` в формате `<< /O /List /ListNumbering /