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 demo를 console sample에서 single-file preflight workflows용 대화형 VCL GUI 도구로 업그레이드했습니다.
  • GUI는 이제 표준 text, JSON, HTML report, 선택적 password, profile INI files, 내장 presets, single-file PDF/VT validation, embedded-report PDF output, report preview, status logging, automatic output naming, 생성 파일 빠른 열기를 지원합니다.
  • command-line arguments가 없을 때 sample PDF와 report를 자동 생성하던 이전 시작 동작을 제거했습니다.

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는 이제 보조 평면 Unicode 출력을 위해 RegisterUnicodeTTF가 생성한 Type 0 글꼴 리소스를 재사용하므로, 페이지 텍스트와 AcroForm appearance stream이 동일한 내부 CID 인코딩 경로를 공유합니다.
  • 공유 finalization 단계는 이제 FUnicodeUsedCps, /CIDToGIDMap, descendant font의 /W, /ToUnicode를 통해 페이지 수준 SMP 출력을 동기화하며, 이전의 페이지 로컬 SMP 맵을 사용하지 않습니다.

2026-05-24 Version 2.121.2

  • `THPDFPage.UnicodeTextOut` 现在将补充平面 Unicode 字符通过页面字体的注册 cmap 格式 12 字形映射进行处理,前提是 `RegisterUnicodeTTF` 已加载活动字体。表情符号和其他 U+10000+ 的标量值以单个字形 CID 的形式输出到页面文本流,而不是两个代理一半的 CID。
  • 페이지 글꼴의 `/ToUnicode` CMap 레코드는 해당 SMP 글리프 CID를 원래 UTF-16BE 서로게이트 쌍으로 다시 변환하여 텍스트 추출 및 접근성을 유지하는 동시에 기존의 `/CIDToGIDMap /Identity` 페이지 글꼴 설정을 그대로 유지합니다.

2026-05-24 Version 2.121.1

  • RegisterUnicodeTTF 기반 AcroForm appearance stream은 이제 emoji 같은 보조 평면 Unicode 문자를 UTF-16 surrogate pair를 두 개의 Identity-H CID로 쓰는 대신 하나의 내부 CID로 렌더링합니다. 생성된 /CIDToGIDMap은 해당 CID를 실제 glyph로 연결하고, /ToUnicode는 텍스트 추출을 위해 원래 UTF-16BE surrogate pair로 다시 매핑합니다.
  • Unicode font finalization 단계는 모든 appearance stream이 늦게 생성된 내부 CID 매핑을 등록한 뒤 /CIDToGIDMap, /W, /ToUnicode를 갱신하므로 TrueType subsetting과 생성된 form appearance가 최종 CID 사용 집합을 사용합니다.

2026-05-23 Version 2.121.0

  • PDF 1.7 §12.6.4.13–15에서 멀티미디어 액션(Rendition / Sound / Movie)에 대해 `THPDFPage` 클래스에 세 가지 새로운 버튼 관련 메서드가 추가되었습니다. `AddPushButtonWithRenditionAction`은 §12.6.4.13에 해당하며, 화면 주석을 MediaRendition 및 MediaClipData와 연결하여 오디오/비디오 클립을 설명하고, /OP 연산 0~4를 사용합니다. `AddPushButtonWithSoundAction`은 §12.6.4.14에 해당하며, 파일 경로 또는 raw `TBytes` 페이로드에 대한 두 가지 오버로드, 호출자가 제공하는 `THPDFSoundParams` 레코드(샘플링 속도 / 채널 / 샘플당 비트 / 인코딩), 그리고 선택적인 /Volume, /Repeat, /Synchronous 옵션을 제공합니다. `AddPushButtonWithMovieAction`은 §12.6.4.15에 해당하며, /Annotation을 통해 Movie 주석을 참조하고, /Operation으로 Play, Stop, Pause, Resume을 선택합니다.
  • `AddScreenAnnotation` 및 `AddMovieAnnotation` 함수는 이제 생성된 주석 딕셔너리를 반환하므로, 호출자는 이를 해당 액션 도우미에 연결할 수 있습니다. `procedure`에서 `function`으로의 시그니처 변경은 Delphi ABI와 호환되며, 기존 호출자가 이 함수들을 호출하고 결과를 버리는 경우에도 컴파일이 가능하고 동일한 바이트 코드를 생성하는 PDF가 생성됩니다.
  • 표준 구현 깊이: 각 도우미는 사양에서 요구하는 필수 항목과 일반적으로 필요한 선택적 필드를 모두 생성합니다. 선택적 미디어 재생 매개변수, 미디어 화면 매개변수, 선택자 렌더링 및 사운드/믹스는 의도적으로 생략되었습니다. 이는 대부분의 경우(약 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 동작은 `/P` 및 `/TF` (TEMPACCESS) 미디어 권한을 MediaClipData 파일 사양과 연결합니다(§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` 테스트(모든 네 가지 액션 유형에 대한 긍정적 경로 커버리지 및 화면/영화 주석 연결) 및 `smoke_multimedia_actions_pdfa_pdfx` 테스트(3가지 액션 × PDF/A + PDF/X를 포괄하는 8개의 게이트 검증)가 성공적으로 완료되었습니다. `smoke_button_actions` 회귀 테스트도 `AddScreenAnnotation` 및 `AddMovieAnnotation` 절차의 함수로의 리팩토링 이후에도 성공적으로 통과했습니다.

2026-05-23 Version 2.120.15

  • 수정 사항: EndDoc 함수는 두 개의 후처리 변환기(v2.84.0의 TrueType 서브세터 및 v2.94.0의 PDF/UA-1 §7.18.3 /Tabs /S 자동 스탬퍼)가 실행되기 전에 PDF 객체 그래프를 직렬화했습니다. 따라서 이러한 변경 사항이 출력 파일에 적용되지 않았습니다. RegisterUnicodeTTF + AddTextField를 호출하는 문서는 전체 글꼴 파일(~1MB Latin / ~14MB CJK)을 포함했지만, 서브세트(~150KB / ~500KB)를 포함하지 않았습니다. 또한, /BaseFont에 AAAAAA+ 서브세트 접두사가 누락되었고, PDF/A의 /CIDSet 스트림이 FontDescriptor에 없었습니다(veraPDF에서 ISO 19005-1 §6.3.5 / -2 -3 §6.2.11 오류로 표시됨). PDF/UA-1 PDF에서 §7.18.3 /Tabs /S 키가 주석 페이지에 없으면 Matterhorn 검사 규칙 21-001 및 PAC 3 "Tabs" 오류가 발생했습니다.
  • 두 개의 수정 함수는 이제 `SaveToStream` / `SaveToFile` 실행 전에 실행됩니다. 이 함수는 `IndirectObjects` 목록을 순회하며 PDF 파일을 작성합니다. 출력 결과는 `v2.120.14`와 동일하며, 이는 Unicode TTF를 등록하지 않거나 `PDFUACompliance`를 활성화하지 않은 문서에 해당합니다. 두 수정 함수는 이미 해당 경우에 아무런 작업도 수행하지 않았으므로, 순서 변경은 `v2.120.14`에서 오류가 발생한 문서에만 영향을 미칩니다.
  • Win32 환경에서 smoke_unicode_ttf_subset 테스트를 통해 검증했습니다 (서브셋은 디스크에 저장된 Arial 파일의 33.6%에 해당하며, 676KB가 절약되었습니다. /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는 이제 PDF 1.7 §14.8.4 표 333에 정의된 41가지 표준 구조 유형(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을 통해 미리 등록한 사용자 정의 역할이 아닌 모든 /S 역할을 거부합니다. 진단 예외에는 문제가 있는 역할 문자열이 포함되어 있으며, PDF/UA-1 §7.7 / 표 333을 참조하고 AddStructRoleMap을 사용한 해결 방법을 제안합니다. 빈 역할도 별도의 메시지와 함께 거부됩니다. 이 검사가 없으면, 규격에 맞지 않는 역할이 구조 트리에 조용히 추가되어 downstream에서 veraPDF / PAC 도구에서 "알 수 없는 구조 유형" 오류로 나타날 수 있습니다.
  • 새로운 게이트는 PDFUACompliance가 True일 때만 작동합니다. UA를 사용하지 않는 호출자는 v2.120.14 이전 버전의 자유 형식 역할 동작을 그대로 유지합니다. 네 가지 AddStructureElement 오버로드(4개의 인수를 받는 AnsiString 기본 오버로드, v2.88.0의 6개의 인수를 받는 /Alt + /ActualText 오버로드, v2.95.0의 7개의 인수를 받는 /ID 오버로드, 그리고 v2.119.41의 THPDFStandardStructureType 열거형 오버로드)는 모두 동일한 경로를 따르므로 하나의 조건문으로 충분합니다. 열거형 오버로드의 경우 항상 표 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.4Ruby+Warichu、§14.8.4.5插图)。还包括StandardStructureTypeToName(T)函数,用于枚举到名称的查找,以及IsStandardStructureType(Name)函数,用于调用方验证。v2.120.14版本将这些功能集成到AddStructureElement入口点,以便自动进行严格检查。一个新的私有辅助函数_IsCustomRoleInRoleMap使用安全的字节比较CompareMem,遍历FStructRoleMap动态数组,并正确匹配自定义的非ASCII角色名称,尤其是在CP_ACP=65001的主机上。

2026-05-23 Version 2.120.13

  • 수정 사항: HotPDF v2.120.12 소스 코드가 RAD Studio에서 빌드되지 않았습니다. 이는 `EnableShapingFeatureForSubset`의 두 가지 오버로드 함수가 `THotPDF`의 공개 섹션 내부에 위치하여 Delphi에서 E2266 오류("오버로드된 메서드 중 하나만 공개될 수 있습니다")를 발생시키기 때문입니다. v2.120.13 버전에서는 두 오버로드 함수를 지역화된 공개 섹션 쌍으로 묶어 동일한 공개 API가 dcc32/dcc64에서 깨끗하게 컴파일되도록 했습니다. 주변 속성 및 도우미 함수는 변경 없이 그대로 유지됩니다. 런타임 동작에는 변경 사항이 없습니다.

2026-05-23 Version 2.120.12

  • EnableShapingFeatureForSubset (8f 단계 완료): THotPDF.EnableShapingFeatureForSubset (FeatureTag) / the THPDFShapingFeature 열거형 오버로드, 요청된 기능에 연결된 모든 GSUB 조회를 순회합니다. SetGSUBScript / SetGSUBLanguage: LookupType 1 (단일 - Format 1에서 Coverage 글리프에 대한 델타 + Format 2 대체 글리프 ID 배열), LookupType 2 (다중 - Sequence.substituteGlyphIDs[]), LookupType 3 (대체 - AlternateSet.alternateGlyphIDs[]), LookupType 4 (리거처 - Ligature.ligatureGlyph), LookupType 5 / 6 (문맥적 / 체인 문맥적 - SequenceLookupRecord 중첩 조회를 재귀적으로 수행하며 깊이 제한은 8), LookupType 7 (확장 - 효과적인 조회 유형으로 자동 해제), LookupType 8 (역 체인 - substituteGlyphIDs[])을 순회합니다. 결과 GID를 FUnicodeExtraUsedGlyphs에 OR 병합하여 v2.84.0 EndDoc 서브세터가 기능에서 생성할 수 있는 모든 글리프를 포함된 글리프 서브세트에 포함하도록 합니다. 8f 단계는 v2.119.50의 각 글리프에 대한 MarkUnicodeGlyphUsed 기능을 보완하며, 기능 제공자 파이프라인에서 기능을 전역적으로 활성화하는 호출자를 위한 기능 수준의 일괄 옵트인 기능을 제공합니다.
  • 열거형 오버로드는 각 THPDFShapingFeature 값을 표준 4바이트 OpenType 기능 태그 세트로 분산합니다. 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. 문자열 태그 오버로드는 번들된 열거형의 경우를 넘어 정확한 타겟팅을 위해 모든 4바이트 OpenType 기능 태그를 허용합니다. 서브셋 불필요한 데이터 증가 경고: 광범위한 기능을 활성화하면(예: aalt, 일부 글꼴은 스크립트의 모든 글리프를 포함) 글꼴의 글리프 세트의 상당 부분을 서브셋으로 가져와 v2.84.0의 크기 감소 효과를 상쇄할 수 있습니다. 호출자는 정확한 GID가 출력되는 경우 Phase 9 MarkUnicodeGlyphUsed를 사용하는 것이 좋습니다. 기본적으로 비활성화되어 있으며, 명시적으로 활성화해야 합니다. GSUB 엔진 로드맵 8단계의 마지막 하위 단계를 완료합니다.
  • 방어적 계약은 v2.119.50과 동일합니다. 폰트가 등록되지 않았거나, GSUB 테이블이 없거나, 4바이트가 아닌 태그가 사용되었거나, (스크립트, 언어) 경로에 해당 기능이 없거나, 룩업 체인이 비어 있는 경우, 이러한 "아무것도 하지 않음" 조건은 예외 없이 무시됩니다 (no-op). 반복적인 호출은 동일한 결과를 가져옵니다 (비트맵은 OR 연산으로 병합됨). 서브 테이블 형식 1/2의 중첩된 룩업 재귀는 향후 버전에서 구현될 예정이며, 현재는 형식 3이 실제 폰트에서 주로 사용되므로 구현되었습니다. 정확한 형식 1/2의 컨텍스트 기반 지원이 필요한 경우, 각 글리프에 대한 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` 함수는 호출자가 등록한 항목을 추가적인 `bfchar` 블록으로 추가합니다. 이러한 블록은 내장된 35개 항목 블록 뒤에 위치하며, Adobe CMap 및 CIDFont 파일 사양(기술 공지 #5014) §1.4.2에 따라 자동으로 100개 항목의 하위 블록으로 분할됩니다. `bfchar` 연산자의 제한은 적용됩니다. BMP 코드 포인트는 4개의 16진 숫자로 출력되고, SMP 코드 포인트는 Adobe CMap 사양에 따라 UTF-16BE 서로게이트 쌍(8개의 16진 숫자)으로 출력됩니다. 등록 순서가 유지되므로 PDF 리더의 "마지막에 쓴 항목이 우선"이라는 동작 방식을 통해 호출자는 내장된 35개 항목과의 충돌 시 일관된 재정의 동작을 얻을 수 있습니다(예: `` "fi"에 대한 사용자 정의 매핑을 등록하면 리더에서 v2.119.65 기본값을 재정의합니다). `RegisterToUnicodeReverseMapping` 함수를 호출하지 않는 경우, `ToUnicode` CMap은 v2.120.10 기준과 동일하게 유지됩니다. `SetFormUnicodeFontDict('', nil)` 함수를 사용하면 경로가 초기화되고 호출자 등록 정보가 지워져 다음 유니코드 폰트 등록이 처음부터 시작됩니다.

2026-05-23 Version 2.120.10

  • 미얀마 텍스트 셰이퍼 (8f.10 단계): 미얀마 스크립트를 등록합니다. (OpenType 태그 `mymr`)를 HotPDF에서 열 번째이자 마지막 인도 스크립트로 등록하며, 미얀마 핵심 블록 (U+1000-U+109F: Burmese, Mon, Sgaw Karen, Western Pwo, Shan, Rumai Palaung, Pa'o)과 확장-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)가 수집되어 R9에 따라 고정된 Y → R → W → H 순서로 방출되며, 이는 원본 순서와 관계없이 적용됩니다.
  • ASAT (U+103A) 및 VIRAMA (U+1039)는 모두 스택된 자음 처리에 있어 virama로 처리됩니다. DOT BELOW (U+1037)는 기본 문자 아래에 렌더링되며, 다른 음조 부호는 위에 렌더링됩니다. ANUSVARA (Bindu)는 위에 표시되고, VISARGA는 뒤에 표시됩니다. Repha는 적용되지 않습니다.
  • 두 개의 `IndicScripts` 레지스트리 항목(기본 블록 및 확장-A)이 동일한 미얀마 재정렬 함수를 사용하므로, 확장-A의 자음과 파오 카렌의 음조 기호가 디스패처를 통해 투명하게 처리됩니다.
  • **11단계의 데바나가리 이외의 인도 문자 변환 일괄 처리 작업을 완료했습니다.** (8f.0 ~ 8f.10 단계): 인프라 구축 및 10개의 등록된 인도 문자 추가 — 데바나가리, 벵골어, 구자라트어, 타밀어, 텔루구어, 칸나다어, 말라얄람어, 싱할라어 (브라흐미 SIA 계열), 크메르어, 미얀마어 (동남아시아).
  • 유니코드 16.0 §16.3 (미얀마) 및 OpenType 미얀마 모양 정의에 따라.

2026-05-23 Version 2.120.9

  • 크메르 텍스트 형상기 (8f.9단계): 크메르 스크립트를 등록합니다. (OpenType 태그 `khmr`, Unicode 블록 U+1780-U+17FF) HotPDF에서 아홉 번째 인도 스크립트이자 첫 번째 동남아시아 스크립트로 등록됩니다. 새로운 `ApplyKhmerReorder` 함수는 사전 처리 단계를 수행하고, `GetKhmerCategory` 함수는 코드 포인트 조회를 수행하며, 이 두 함수는 `ApplyIndicReorder` 디스패처를 통해 재사용 가능합니다.
  • 독립적인 음절 구조 (브라흐미 문자 R1-R5 패턴이 아닌): 전음 (E / AE / AI / OE / OO / AU)은 음절 시작 부분으로 이동합니다. 음절 변환 문자 (MUUSIKATOAN, TRIISAP) 및 기타 상위 문자들은 상위 버퍼로 전달됩니다. Bindu (NIKAHIT)는 위쪽에 렌더링됩니다. Visarga (REAHMUK, YUUKALEAPINTU)는 뒤쪽에 렌더링됩니다.
  • COENG 서브스크립트 처리: 각 COENG (U+17D2)에 추가된 자음 쌍은 원래 순서대로 기본 버퍼에 저장된 중첩된 자음 클러스터를 형성하며, 글꼴의 'pres' / 'blws' GSUB 기능을 사용하여 서브스크립트 위치를 조정합니다. 중첩된 COENG도 지원됩니다.
  • 크메르 문자 스크립트는 Repha 시각적 요소를 형성하지 않으므로, `Ra + COENG + 자음`은 원래 순서를 유지하며, 음절 끝으로 회전하지 않습니다.
  • 유니코드 16.0 §16.4 (크메르어) 및 OpenType 크메르어 형태 지정 사양에 따라.

2026-05-23 Version 2.120.8

  • PAdES **adbe-revocationInfoArchival** CMS 서명 속성 (PAdES Phase 9): Adobe의 개인 OID를 생성합니다. 1.2.840.113583.1.1.8은 CRL 및 OCSP 해제 값을 CMS 서명 자체 내부에 포함합니다. Adobe Acrobat은 DSS 사전 검색 및 네트워크 OCSP/CRL 검색보다 이 속성을 우선적으로 사용하여 서명 해제 확인을 수행하며, 이는 오프라인에서도 유효성을 검사할 수 있는 PDF 파일에 중요하며, Adobe Acrobat과의 최상의 호환성을 제공합니다.
  • 새로운 `THPDFCMSSignOptions` 필드:
    • AdobeCRLsDER: TBytes 배열 - 각 항목은 X.509 `CertificateList` (RFC 5280) DER 인코딩이며, DSS `/CRLs` 스트림에 포함된 것과 동일한 형식입니다.
    • AdobeOCSPsDER: TBytes 배열 - 각 항목은 `BasicOCSPResponse` SEQUENCE (RFC 6960 §4.2.1) DER 인코딩입니다. 참고: 외부 `OCSPResponse` 래퍼가 아닌 `responseBytes.response` OCTET STRING을 먼저 언래핑하여 `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] (X.509이 아닌 시스템의 경우의 otherRevInfo)는 범위를 벗어납니다.
  • 와이어 모양 (두 분기 모두 채워짐): 30 A0 30 <...> A1 30 <...>
  • **DSS 사전과 함께 사용 가능:** 이 속성은 *PAdES-B-LT DSS 사전의 *병렬* 속성입니다 (대체하는 것이 아닙니다). (v2.110.0에 도입된 카탈로그 레벨의 `/DSS /Certs /OCSPs /CRLs /VRI). 엄격한 PAdES 검증기(EU DSS, mTOM)는 일반적으로 DSS를 준수하며, Adobe Acrobat은 `adbe-revocationInfoArchival`을 준수합니다. 최대 호환성을 위해, `AddPAdESDSSCRL / AddPAdESDSSOCSP 및 `AdobeCRLsDER / AdobeOCSPsDER를 사용하여 동일한 CRL/OCSP 바이트를 두 계층 모두에 채워 넣으십시오.
  • 4개의 인수를 받는 `HPDFCMSBuildSignedData` 래퍼는 새로운 필드를 0으로 설정하여 기존 CMS 번들이 바이트 단위로 동일하게 유지되도록 합니다.
  • Adobe Acrobat PDF 참조, 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)은 서명 전에 문서 내용이 존재했음을 증명하는 사전 서명 RFC 3161 TimeStampToken을 포함합니다. 이는 signature-time-stamp (서명 후 적용되는, 서명이 없는 속성, Phase 4)와 다릅니다.
  • 새로운 `THPDFCMSSignOptions` 필드 추가. `GetContentTimeStamp: THPDFCMSTimestampCallback`. v2.120.3 버전의 `GetSignatureTimeStamp` 기능과 유사하게 구현되었습니다. HotPDF는 콜백 함수를 호출하여 문서의 SHA-256 해시 값(서명된 속성에 포함된 해시 값과 동일)을 전달하고, 반환된 TimeStampToken DER 데이터를 SignedAttributes 내의 content-time-stamp 속성 값으로 포함합니다.
  • 기본적으로 `nil`은 콘텐츠 타임스탬프가 생성되지 않음을 의미합니다. 콘텐츠 타임스탬프를 사용하려면, RFC 3161에 따른 TSA(Timestamping Service)를 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가 필요하며, 법적 효력이 없는 서명은 무료 엔드포인트를 사용하여 가능합니다 (속도 제한이 있지만 일반적인 워크플로우에는 충분합니다).
  • 콜백 계약: 서명 작업당 한 번 호출됩니다. 서명된 속성이 최종적으로 결정되기 에 호출됩니다. TST 바이트는 서명되는 내용의 일부가 되므로, 서명 자체는 콘텐츠-타임스탬프를 포함합니다. 이것이 서명된 속성인 이유이며(서명-타임스탬프는 서명이 없고 unsignedAttrs에 저장됨).
  • 4개의 인수를 받는 `HPDFCMSBuildSignedData` 래퍼는 `GetContentTimeStamp:=nil`로 설정하여 기존 CMS 번들이 바이트 단위로 동일하게 유지되도록 합니다.
  • 호출자 책임: PAdES 플레이스홀더는 서명과 콘텐츠 타임스탬프(TST)를 포함할 수 있도록 크기가 조정되어야 합니다(일반적으로 ~4-8KB). 콘텐츠 타임스탬프와 서명 타임스탬프를 결합하는 B-T 워크플로우의 경우, 두 개의 TST를 모두 고려해야 합니다. `AddPAdESSignatureField(Profile='B-T')`의 기본값인 16KB는 대부분의 조합을 충분히 커버합니다.
  • 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 서명자 속성 v2 **signedAssertions [2]** 브랜치 (PAdES Phase 7): 세 번째이자 마지막 서명자 속성 v2 선택적 필드를 종료합니다. 이를 통해 서명자는 OID로 식별되는 서명된 어설션을 CMS 서명 내부에 첨부할 수 있습니다. (SAML 2.0 어설션, JWT 압축 형식 토큰, OAuth 증명, 조직별 증명 토큰 등).
  • 새로운 `THPDFSignedAssertion` 레코드: `SignedAssertionID` (어설션 유형을 식별하는 점선 OID)와 `AssertionBody: TBytes`를 포함합니다. `AssertionBody`는 OID의 스키마에서 정의하는 사전 인코딩된 임의의 바이트이며, 일반적으로 SAML XML 또는 JWT의 압축 형식을 래핑하는 OCTET STRING입니다. `AssertionBody`가 비어 있으면 임의 필드가 생략되고 `signedAssertionID`만 남게 됩니다(OID로 등록된 부울 스타일 어설션의 경우 사양에 유효합니다).
  • 새로운 `THPDFCMSSignOptions` 필드가 추가되었습니다. `SignedAssertions`: `THPDFSignedAssertion` 객체의 배열입니다. 여러 개의 서명 정보를 지원하며, HotPDF은 이를 `[2] EXPLICIT` (태그 `0xA2`)으로 감쌉니다.
  • SignerAttributeV2 조건이 이제 세 개의 선택적 필드 중 하나라도 채워지면 트리거됩니다. 세 개의 필드를 모두 채우면 다음과 같은 내용이 spec 필드에 생성됩니다. 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) assertion OID 인코딩을 수행합니다. 점 표기법으로 표현된 모든 OID가 허용됩니다.
  • 4개의 인수를 받는 `HPDFCMSBuildSignedData` 래퍼 함수는 새로운 필드를 0으로 설정하여 기존 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

  • PAdES signer-attributes-v2 **certifiedAttributesV2** [1] 분기 (PAdES Phase 6): X.509 속성 인증서를 SignerAttributeV2 시퀀스 내부에 포함시킵니다. 이는 v2.120.4의 claimedAttributes [0]과 함께 사용하거나 대체하여 사용할 수 있습니다. 이를 통해 서명자는 AA(속성 권한)에서 발급한 인증서를 첨부하여 주장된 신원/역량을 암호학적으로 보장할 수 있습니다.
  • 새로운 `THPDFCMSSignOptions` 필드가 추가되었습니다. `CertifiedAttributeCertsDER: TBytes 배열`. 각 항목은 발급 기관(AA)으로부터 수신한 완전한 DER 인코딩된 `AttributeCertificate` (RFC 5755)입니다. HotPDF은 이를 변경하지 않고 `[1] EXPLICIT` (태그 `0xA1`)로 묶인 `CertifiedAttributesV2 SEQUENCE OF`에 포함시킵니다.
  • `signer-attributes-v2` 속성은 이제 다음 조건 중 하나라도 충족될 때 생성됩니다. `ClaimedRoles` 또는 `CertifiedAttributeCertsDER`가 비어 있지 않은 경우입니다. 두 속성 모두 채워지면 `SignerAttributeV2` 시퀀스가 생성되며, 이는 `[0]`과 `[1]`을 결합하여 사양의 순서와 일치하도록 합니다.
  • ASN.1 DER 바이트 형식 (CertifiedAttributesV2만 해당): A1 30 여기서 각 ACn은 호출자가 제공하는 RFC 5755의 AttributeCertificate SEQUENCE를 그대로 사용합니다. AttributeCertificateOtherAttributeCertificate 사이의 선택은 호출자가 제공하는 DER 입력에 의해 결정됩니다 (두 가지 옵션 모두 SEQUENCE 0x30 태그로 시작합니다. HotPDF는 내부 구조를 분석하지 않습니다).
  • `HPDFCMSBuildSignedData` 함수의 4개 인자 래퍼는 새로운 필드를 0으로 설정하여 이전 버전(v2.119.27)과 동일한 바이트 크기를 유지하도록 합니다.
  • 범위: signedAssertions [2] (SAML / JWT / 임의 OID 토큰)은 아직 처리 중이며 다음 단계에서 제공될 예정입니다.
  • ETSI EN 319 122-1 V1.2.1 §5.2.6, 부록 A.1 및 RFC 5755에 따름.

2026-05-23 Version 2.120.4

  • PAdES **signer-attributes-v2** CMS 서명 속성 (PAdES Phase 5): 다음 속성을 생성합니다. id-aa-ets-signerAttrV2 (OID 0.4.0.19122.1.1, ETSI EN 319 122-1 §5.2.6), 이를 통해 서명자는 CMS 번들 내에서 자신이 주장하는 역할을 선언할 수 있습니다 (예: "최고 재무 책임자", "인가된 대리인"). 이 기능은 새로운 서명에 대해 더 이상 사용되지 않는 v1 signerAttr (RFC 5126 §5.10)을 대체합니다.
  • 새로운 `THPDFClaimedRole` 레코드: `RoleOID` (점 표기법으로 표현된 속성 유형 OID, 일반적으로 조직 역할 OID 또는 `1.3.6.1.5.5.7.20.1 id-id-aa-PERMrole` ID) + `RoleValue` (사람이 읽을 수 있는 역할 레이블을 포함하는 UTF-8 문자열).
  • 새로운 `THPDFCMSSignOptions` 필드가 추가되었습니다. `ClaimedRoles`: `THPDFClaimedRole` 유형의 배열입니다. 여러 역할을 지원하며, 각 역할은 `claimedAttributes [0]` 시퀀스 내의 하나의 `Attribute`가 됩니다. 빈 배열(기본값)은 해당 속성을 제거하며, v2.120.3 버전에서 바이트 수준의 안정성을 유지하여, 해당 기능을 사용하지 않으려는 사용자를 위한 호환성을 제공합니다.
  • ASN.1 DER 표준에 따라 ETSI EN 319 122-1 §5.2.6 및 부록 A.1에 명시된 내용(모듈 정의, 명시적 태그): `SignerAttributeV2 SEQUENCE { [0] EXPLICIT ClaimedAttributes }`이며, 여기서 `ClaimedAttributes ::= SEQUENCE OF Attribute`입니다. 각 역할은 `Attribute { type OID, values SET OF UTF8String }` 형식으로 직렬화됩니다. 명시적 태그는 `0xA0`이 내부 `SEQUENCE OF`를 그대로 감싸는 것을 의미합니다(내부 `0x30` 태그는 유지됩니다).
  • OID 본문은 수동으로 인코딩되었습니다. 04 00 81 95 32 01 01 (arc 0.4.0.19122.1.1; base-128 계속: 19122 → 0x81 0x95 0x32). 향후 사용자 정의 값은 v2.120.1부터 제공되는 CMSEncodeOIDFromString을 사용할 수 있습니다.
  • **범위 제한:** `claimedAttributes [0]`만 구현되었습니다. `certifiedAttributesV2 [1]` (RFC 5755에 따른 X.509 속성 인증서) 및 `signedAssertions [2]` (SAML/JWT 스타일 토큰)은 추가적인 기능이 필요하며, 구체적인 요구 사항이 발생할 때까지 제외됩니다.
  • 4개의 인수를 받는 `HPDFCMSBuildSignedData` 래퍼가 0으로 설정되어, 기존 CMS 번들이 v2.119.27 버전과 동일한 바이트 크기를 유지하도록 합니다.
  • ETSI EN 319 122-1 V1.2.1 §5.2.6 및 EN 319 142-1 V1.2.1 §6.3의 표 1에서, "signer-attributes-v2" 행은 (선택 사항이며, 0 또는 1).

2026-05-23 Version 2.120.3

  • PAdES **서명 시간 정보** 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 SET 내에 포함합니다. PAdES-B-T 신뢰할 수 있는 시간 서비스에 대한 **서명 시간 정보** 경로를 제공합니다 (표 1: B-T는 반드시 서명 시간 정보 또는 문서 시간 정보를 통해 제공되어야 합니다).
  • 새로운 `THPDFCMSTimestampCallback` 익명 메서드 유형: `reference to function(const SigValueSHA256: TBytes): TBytes`. HotPDF은 `SignerInfo.signatureValue`의 SHA-256 해시 값(RFC 3161의 §2.4.2에 정의된 `messageImprint`에 해당)을 사용하여 콜백 함수를 호출하고, 반환된 `TimeStampToken` DER 데이터를 속성 값으로 포함합니다.
  • 새로운 `THPDFCMSSignOptions` 필드인 `GetSignatureTimeStamp`가 추가되었습니다. 기본값은 `nil`이며, 이는 타임스탬프를 사용하지 않음을 의미합니다. PAdES-B-T를 사용하는 경우, TSA HTTP/RFC 3161 상호 작용을 처리하고 TST 바이트를 반환하는 클로저를 할당해야 합니다. 빈 TBytes를 반환하면 오류 없이 건너뜁니다 (예: TSA에 접근할 수 없지만 서명은 여전히 생성됩니다).
  • 네트워크/인증/TSA 계정 처리는 호출 코드에 유지되며, HotPDF은 결과를 `unsignedAttrs`에 전달합니다. 이는 기존 `AddPAdESSignatureField(Profile='B-T', ContentsBytes >= 16384)`의 플레이스홀더 크기 조정과 자연스럽게 호환됩니다.
  • ASN.1 와이어 형식에서, `SignerInfo` 시퀀스는 이제 선택적으로 `[1] IMPLICIT SET OF Attribute` (태그 `0xA1`)를 포함할 수 있으며, 이 `Attribute`는 `signature-time-stamp` 속성을 가지며, 그 값은 호출자가 제공한 `TimeStampToken ContentInfo`를 그대로 포함합니다.
  • 4개의 인수를 받는 `HPDFCMSBuildSignedData` 래퍼는 `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), 서명이자(signer)가 서명을 통해 제공하는 약속의 유형을 선언합니다 (예: 원본 증명 / 수령 증명 / 배송 증명 / 발신자 증명 / 승인 / 생성).
  • 새로운 `THPDFCommitmentType` 열거형이 추가되었습니다. `ctNone` (기본값이며, 해당 속성을 비활성화합니다.), `ctProofOfOrigin`, `ctProofOfReceipt`, `ctProofOfDelivery`, `ctProofOfSender`, `ctProofOfApproval`, `ctProofOfCreation` (RFC 5126 §5.11.1에 정의된 여섯 개의 표준 `id-cti-ets-*` OID, 즉 `1.2.840.113549.1.9.16.6.{1..6}`), 그리고 `ctCustom` (호출자가 새로운 `CommitmentTypeOID` 필드를 통해 임의의 OID를 제공합니다).
  • 활성화: `THPDFCMSSignOptions.CommitmentType`가 `ctNone`이 아닐 때마다 발생합니다. 빈 기본값은 v2.120.1에서 바이트 수준의 안정성을 유지하여 옵트인하지 않은 호출자에게 영향을 미칩니다.
  • **사용자 책임 (PAdES Part 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가 식별자를 정의하지 않기 때문에 생략되었습니다. 식별자가 필요한 사용자 정의 커밋은 해당 기능을 확장할 수 있습니다.
  • 4개의 인수를 받는 `HPDFCMSBuildSignedData` 래퍼는 새로운 `CommitmentType` 필드를 0으로 설정하여 기존 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 지원 (PAdES Phase 2): `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 (Part 2 V1.2.1 §5.4 Table 2)에서는 반드시 포함되어야 하며, 다른 모든 PAdES 레벨에서는 선택적으로 포함될 수 있습니다.
  • 새로운 `THPDFCMSSignOptions` 레코드 필드: `SignaturePolicyOID` (정책 문서의 점선 OID 문자열), `SignaturePolicyHash` (정책 문서의 해시 값), `SignaturePolicyHashAlgOID` (해시 알고리즘 OID, 비어 있으면 기본적으로 SHA-256 사용), 그리고 `SignaturePolicyURI` (선택 사항이며, RFC 5126 §5.8.1에 따른 SPuri 자격 증명, OID는 `1.2.840.113549.1.9.16.5.1`이며, 정책 문서 URL을 가리킵니다).
  • 활성화: 정책 속성은 호출자가 `SignaturePolicyOID`와 `SignaturePolicyHash`를 모두 채웠을 때만 생성됩니다. 빈 기본값은 해당 속성이 생략됨을 의미하며, 기본 서명 생성기는 v2.120.0 출력에서 바이트 수준의 안정성을 유지합니다.
  • 새로운 CMSEncodeOIDFromString 함수는 임의의 점 표기법 OID를 X.690 §8.19에 따라 DER 형식으로 인코딩합니다 (처음 두 개의 부분은 `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 버전에서 새로운 정책 필드를 채우지 않은 경우에도, 출력 결과는 이전 버전과 동일합니다. 4개의 인수를 사용하는 `HPDFCMSBuildSignedData` 래퍼는 새로운 필드를 0으로 설정하여 기존 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

  • PAdES 기본 CMS 속성 준수 (PAdES 1단계): `SignPDFWithPFX`는 이제 기본적으로 **ESS 서명 인증서 v2** 서명 속성(RFC 5035 / OID `1.2.840.113549.1.9.16.2.47`)을 생성하며, 이를 통해 서명 인증서의 식별자를 위조 공격으로부터 보호합니다. ETSI EN 319 142-1 V1.2.1 §6.3 표 1에 따르면, 이 속성은 모든 기본 수준(B-B / B-T / B-LT / B-LTA)에서 *반드시 제공되어야 합니다*.
  • PAdES 기본 설정에서 이제 CMS `signing-time` 속성이 기본적으로 생략됩니다. 표 1에서는 기본 프로필에 대해 이 속성의 개수가 0이어야 함을 명시합니다 (표 1의 주석 g에 따라 서명 시간은 Signature Dictionary의 `/M` 항목에 포함됨). 이전 버전 v2.119.27에서는 프로필에 관계없이 `signing-time` 속성이 포함되었으며, 이는 엄격한 PAdES 검증기(EU DSS, Adobe Acrobat의 PAdES 기본 설정 모드)에서 거부됩니다.
  • 새로운 공개 API: `THPDFPAdESLevel` 열거형 (8개의 값, 기본 B-B / B-T / B-LT / B-LTA, 확장 E-BES / E-EPES / E-LTV, 그리고 기존 `adbe.pkcs7` 포함), `THPDFCMSSignOptions` 레코드 (레벨, 서명 시간, 서명 인증서 v2 옵션, UTC 타임스탬프 포함), 레벨별로 규격 준수 기본값을 반환하는 `HPDFCMSDefaultOptions(Level)` 도우미, 그리고 옵션 기반 CMS 빌더 `HPDFCMSBuildSignedDataEx`.
  • 이전 버전과의 호환성: v2.119.27 버전의 네 가지 인수를 사용하는 `HPDFCMSBuildSignedData` 서명은 기존 방식을 유지하며, 바이트 단위로 동일한 출력을 생성합니다 (서명 인증서 v2는 사용되지 않으며, 요청된 대로 서명 시간 정보가 포함됨). 테스트에서 v2.119.27 CMS 번들을 해시 처리하던 기존 코드는 계속 정상적으로 작동합니다.
  • 서명된 PDF 출력의 동작 변경: `THotPDF.SignPDFWithPFX`를 호출하여 PAdES 플레이스홀더에 서명하는 모든 경우 ( `AddPAdESSignatureField`, SubFilter `ETSI.CAdES.detached` 사용) 이제 엄격한 PAdES 기본 검증을 통과하는 서명이 생성됩니다. v2.119.27 레거시 속성 세트를 사용하려면 `HPDFCMSBuildSignedDataEx`를 직접 호출하고 `HPDFCMSDefaultOptions(palLegacy_adbePkcs7)`를 사용하십시오.
  • RFC 5035 §3에 정의된 ASN.1 DER 구조를 사용하며, SHA-256 알고리즘 식별자를 사용합니다. (X.690 §11.5의 기본값 DER 규칙에 따라 SHA-256 인증서 해시를 생략). `IssuerSerial`은 기존의 `CMSExtractIssuerAndSerial`에서 추출하는 X.509 발급자 및 시리얼 번호를 재사용합니다.
  • ETSI EN 319 142-1 V1.2.1 §6.3 표 1 및 RFC 5035 §3에 따름.

2026-05-23 Version 2.119.77

  • 싱할라 문자 모양 기능이 추가되었습니다 (8단계 f.8). 싱할라어 ('sinh', U+0D80-U+0DFF)가 8번째로 등록된 인도 문자 스크립트가 되었습니다. 새로운 ApplySinhalaReorderGetSinhalaCategory 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는 3부분으로 구성됩니다 (E + AA + AL-LAKUNA).
  • `ApplyIndicReorder` 디스패처가 싱할라어를 투명하게 지원합니다 (IndicScripts 레지스트리는 이제 array[0..7] 배열입니다).
  • 21개의 새로운 DUnitX 테스트가 추가되었습니다. 총 187개의 테스트 중 187개가 Win32 및 Win64 환경에서 통과했습니다.
  • 유니코드 16.0 §12.11 (신할라어) 및 OpenType 신할라어 모양 정의 사양에 따라.

2026-05-23 Version 2.119.76

2026-05-23 Version 2.119.75

  • 칸나다어 형태 분석 기능이 추가되었습니다 (GSUB 엔진 로드맵 8f.6 단계). 칸나다어 ('knda', U+0C80-U+0CFF)는 여섯 번째로 등록된 인도 문자입니다. `THotPDF` 클래스에 새로운 공개 메서드인 `ApplyKannadaReorder` 및 `GetKannadaCategory`가 추가되었습니다.
  • 칸나다어는 데바나가리, 벵골어, 구자라트어, 텔루구어와 마찬가지로 Repha (Ra=U+0CB0 + Halant=U+0CCD)를 사용합니다. 텔루구어와 마찬가지로 칸나다어에는 기본 음절 위에 붙는 음절 기호가 없습니다. 칸나다어의 모든 음절 기호는 기본 음절 위, 아래, 뒤 또는 분리된 형태로 나타납니다.
  • 유니코드 16.0의 표준 분해 방식을 사용하여 5개의 마트라를 분리했습니다. 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` 디스패처는 레지스트리를 통해 칸나다 문자를 투명하게 처리합니다 (현재는 array[0..5]로 구성).
  • 테스트: 21개의 새로운 DUnitX 테스트 케이스가 추가되었으며, 여기에는 5가지 분리 마트라 케이스와 전용 3부 OO 검증이 포함됩니다. 총 145개의 테스트 중 145개가 Win32 및 Win64에서 통과했습니다.
  • 유니코드 16.0 §12.9 (칸나다어) 및 OpenType 칸나다어 모양 정의에 따라.

2026-05-23 Version 2.119.74

  • 텔루구어 모양 기능이 추가되었습니다 (GSUB 엔진 로드맵 8f.5 단계). 텔루구어 ('telu', U+0C00-U+0C7F)는 다섯 번째로 등록된 인도 문자입니다. `THotPDF` 클래스에 새로운 공개 메서드인 `ApplyTeluguReorder` 및 `GetTeluguCategory`가 추가되었습니다.
  • 텔루구어는 데바나가리/벵골어/구자라트어와 마찬가지로 Repha (Ra=U+0C30 + Halant=U+0C4D)를 사용합니다. 그러나 이전의 모든 인도 문자 체계와 달리, 텔루구어에는 사전 기본 기호가 없습니다. 모든 텔루구어 기호는 기본 위, 기본 아래 또는 분리된 형태로 사용됩니다.
  • 기본 문자 위에 위치하는 추가적인 기호(R3): AA/I/II/E/EE/O/OO/AU 및 길이 표시 U+0C55. 기본 문자 아래에 위치하는 기호(R4): U/UU/Vocalic 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` 디스패처는 레지스트리를 통해 텔루구어를 투명하게 처리합니다 (현재는 array[0..4]로 구성).
  • 테스트: 17개의 새로운 DUnitX 테스트 케이스가 추가되었습니다. 총 124개의 테스트 중 124개가 Win32 및 Win64에서 통과했습니다.
  • 유니코드 16.0 §12.8 (텔루구어) 및 OpenType 텔루구어 모양 지정 사양에 따라.

2026-05-23 Version 2.119.73

  • 타밀어 모양 기능이 추가되었습니다 (GSUB 엔진 로드맵 8f.4 단계). 타밀어 ('taml', U+0B80-U+0BFF)는 네 번째로 등록된 인도 문자입니다. `THotPDF` 클래스에 새로운 공개 메서드인 `ApplyTamilReorder` 및 `GetTamilCategory`가 추가되었습니다.
  • 타밀어는 다른 브라흐미 문자 체계와 다음과 같은 차이점을 보입니다. '레파'가 없습니다 (타밀어는 전통적으로 '레파' 시각적 형태를 사용하지 않습니다). 'I-마트라' (U+0BBF)는 다른 브라흐미 문자 체계에서는 찾아볼 수 없는, 기본 글자 뒤에 위치합니다. 'II' (U+0BC0)는 기본 글자 위에 위치합니다. 'E/EE/AI' (U+0BC6-U+0BC8)는 기본 글자 앞에 위치합니다. 3개의 분리된 마트라가 있으며, 각각 U+0BCA (O = U+0BC6+U+0BBE), U+0BCB (OO = U+0BC7+U+0BBE), U+0BCC (AU = U+0BC6+U+0BD7)입니다.
  • Halant은 타밀어에서 U+0BCD에서 "PULLI"로 명명됩니다. `ApplyIndicReorder` 디스패처는 레지스트리를 통해 타밀어를 투명하게 인식합니다 (현재 array[0..3] 배열 사용).
  • 테스트: 20개의 새로운 DUnitX 테스트 케이스가 추가되었습니다. 총 107개의 테스트 중 107개가 Win32 및 Win64에서 통과했습니다.
  • 유니코드 16.0 §12.7 (타밀어) 및 OpenType 타밀어 모양 지정 사양에 따라.

2026-05-23 Version 2.119.72

  • 구자라트어 형태 지정 기능이 추가되었습니다 (GSUB 엔진 로드맵 8f.3 단계). 구자라트어 ('gujr', U+0A80-U+0AFF)는 데바나가리 및 벵골어를 잇는 세 번째 등록된 인도 문자입니다. `THotPDF` 클래스에 새로운 공개 메서드인 `ApplyGujaratiReorder` 및 `GetGujaratiCategory`가 추가되었습니다.
  • 규칙 재정렬: R1 Repha (Ra=U+0AB0 + Halant=U+0ACD), R2 pre-base (U+0ABF I), R3 위쪽 기본 (U+0AC5 CANDRA E, U+0AC7 E, U+0AC8 AI – 구자라트어에서 위쪽 기본은 데바나가리와 같고, 벵골어처럼 아래쪽 기본이 아님), R4 아래쪽 기본 (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). 분리된 matras는 없습니다.
  • `ApplyIndicReorder` 디스패처는 `IndicScripts` 레지스트리(현재 array[0..2])를 통해 구자라트어를 투명하게 처리합니다. `BuildUnicode*FieldContent` 통합 기능은 `sfIndicShaping` 설정을 사용하여 구자라트어를 처리하며, 이로 인해 통합 변경 사항이 전혀 발생하지 않습니다.
  • 테스트: R3의 기본 범위를 초과하는 18개의 새로운 DUnitX 테스트 케이스가 추가되었습니다. 이 테스트는 구자라트어의 E/AI 처리 방식을 벵골어와 구별하는 데 사용됩니다. 총 87개의 테스트 중 87개가 Win32 및 Win64에서 통과했습니다.
  • 유니코드 16.0 §12.6 (구자라트어) 및 OpenType 구자라트어 모양 정의 사양에 따라.

2026-05-23 Version 2.119.71

  • 벵골 문자 모양 기능이 추가되었습니다 (GSUB 엔진 로드맵 8f.2 단계). 벵골 문자 ('beng', U+0980-U+09FF)는 데바나가리 문자 이후 두 번째로 등록된 인도 문자입니다. `THotPDF` 클래스에 새로운 공개 메서드인 `ApplyBengaliReorder` 및 `GetBengaliCategory`가 추가되었으며, 이는 8e 단계의 데바나가리 API와 동일한 기능을 제공합니다.
  • 벵골어 재정렬 규칙: 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` 설정과 함께 벵골어와 데바나가리를 모두 지원하며, 통합 변경 사항은 없습니다.
  • 테스트: 벵골어 R1/R2/R4/R5을 포함한 18개의 새로운 DUnitX 테스트 케이스가 추가되었습니다. 이 테스트는 분해, 결합 문자 보존, 혼합 스크립트 처리,멱등성 및 디스패처 동등성을 검증합니다. 총 69개의 테스트 케이스가 Win32 및 Win64 환경에서 모두 통과했습니다.
  • 유니코드 16.0 §12.2 (벵골어) 및 OpenType 벵골어 모양 지정 사양에 따라.

2026-05-23 Version 2.119.70

  • 데바나가리 완성형자 모양 변경 (GSUB 엔진 로드맵 8f.1 단계): `ApplyDevanagariReorder` 함수는 이제 v2.119.55 버전에서 제공되던 R1 + R2만 적용하는 방식 대신, 전체 5단계 재정렬 규칙(R1 Repha + R2 pre-base + R3 above-base + R4 below-base + R5 post-base)을 적용합니다. 출력 클러스터 순서는 음절별로 다음과 같습니다: `[pre-matras] + [base + halant + nukta + bindu/visarga/ modifier] + [above-matras] + [below-matras] + [post-matras] + [Repha]`.
  • 자음-후음-자음 결합은 기본 블록 내에서 그룹화된 상태로 유지됩니다. 재정렬은 오직 마트라(vowel mark)와 레파(Repha)에만 적용됩니다. 단일 패스 방식으로 작동하며, 동일한 작업을 반복해도 결과가 동일합니다.
  • v2.119.69 버전과의 동작 변경 사항: 위에/아래/기본 매트라 뒤에 오는 음절의 경우, PDF 바이트 스트림이 이제 표준 재정렬 레이아웃을 반영합니다. GSUB/GPOS 이후의 시각적 렌더링은 변경되지 않았습니다. R1 Repha 또는 R2 pre-base I-matra만 포함된 입력(v2.119.55 버전)의 경우, 바이트 수준에서 동일한 출력을 생성합니다.
  • 테스트: R3, R4, R5 각각에 대한 8개의 새로운 DUnitX 테스트 케이스가 추가되었으며, 다중 마트라 순서, 마트라 하에서의 연결 문자 보존, Repha + 상단 + 후행 문자 혼합, 그리고 다중 마트라의 중복성 테스트를 포함합니다. 총 51개의 테스트 케이스가 Win32 및 Win64 환경에서 모두 통과했습니다.
  • 유니코드 16.0 §12.1 (데바나가리) 및 OpenType 데바나가리 모양 정의 사양에 따라.

2026-05-23 Version 2.119.69

  • 인도 문자 형태 변환 인프라 (GSUB 엔진 로드맵 8f.0): v2.119.55 / v2.119.67 버전의 데바나가리 재정렬 사전 처리 단계를 스크립트 독립적인 디스패치 프레임워크로 재구성했습니다. 새로운 타입 `TIndicScriptInfo`, `TIndicCategoryFunc`, `TIndicFindSyllableFunc`, `TIndicReorderFunc` 및 새로운 `IndicScripts` 레지스트리를 통해 향후 인도 문자 스크립트가 함수 포인터를 통해 통합될 수 있도록 했습니다.
  • 새로운 공개 메서드 `ApplyIndicReorder(Wide)`는 `Wide`의 모든 코드 포인트를 해당 등록된 스크립트로 전달하고, 해당 스크립트의 음절 재정렬 콜백을 적용합니다. 인도 스크립트가 아닌 내용은 변경 없이 그대로 통과됩니다.
  • `BuildUnicode*FieldContent` 함수는 이제 `sfIndicShaping`이 `FShapingFeatures`에 포함되어 있을 때 `ApplyIndicReorder` 함수를 호출합니다 (Devanagari 전용 래퍼 대신). 8f.0 버전은 Devanagari만 지원하며, 이후 8f.2부터 8f.10까지의 버전에서는 Bengali, Gujarati, Tamil, Telugu, Kannada, Malayalam, Sinhala, Khmer, Myanmar을 추가하지만, 이 통합 방식은 변경되지 않습니다.
  • 기존의 `ApplyDevanagariReorder` 함수는 v2.119.55 버전과의 호환성을 유지하기 위해 Devanagari 문자만 처리하는 래퍼 함수로 유지됩니다. 출력 결과는 v2.119.67 버전과 동일합니다.
  • 유니코드 16.0 §12 (남아시아 문자) 및 ISO 32000-1 §9.10에 따라.

2026-05-22 Version 2.119.68

  • 8c.6 단계: 프로듀서 측에서 GID 수준의 코드를 생성하며, 이는 개인 사용 영역(PUA)의 합성 코드 포인트 매핑을 통해 이루어집니다. THotPDF 클래스에 두 개의 새로운 공개 메서드가 추가되어, 호출자가 자연스러운 Unicode 코드 포인트가 없는 대체 GID를 생성할 수 있도록 합니다. AssignSyntheticCodepointForGID(GID; out SyntheticCP): Boolean 메서드는 사용 가능한 PUA 슬롯을 할당하고, 이 할당을 FUnicodeCpToGid, FAcroFormUnicodeAdvances 및 새로운 FUnicodeSyntheticCpForGID 테이블에 반영합니다. 이렇게 하면 기존의 프로듀서 측 16진수 인코딩 파이프라인이 합성 코드 포인트를 4자리 16진수 토큰으로 출력하고, 소비자 리더는 이를 /CIDToGIDMap을 통해 대체 글리프로 변환합니다. GetSyntheticCodepointForGID(GID): Word 메서드는 기존 할당을 쿼리하며, 할당되지 않은 경우 0을 반환합니다. 두 메서드 모두멱등성을 가지므로, 동일한 GID에 대해 반복적으로 호출하면 동일한 합성 코드 포인트가 반환됩니다.
  • 글꼴별 GSUB 대체 항목에 대한 프로듀서 측 기능을 활성화하며, 이 항목들은 Unicode Presentation Form 코드 포인트를 갖지 않습니다. 여기에는 Devanagari 클러스터 모양(Indic 'akhn' / 'rphf' / 'pres' / 'blws' / 'psts' / 'haln' 출력은 일반적으로 글꼴 내부 GID에 위치함), 스타일 대체('salt' / 'ss01-20' 대체 항목은 코드 포인트를 갖지 않음), 선택적 리가처('dlig' / 'hlig' 글꼴별 글리프) 및 CJK 표의어 변형 시퀀스 대체가 포함됩니다. v2.119.43-50 GSUB 엔진 API 및 v2.119.50 MarkUnicodeGlyphUsed 서브세터 클로저와 결합하여, 이제 호출자는 기존 코드 포인트 기반 16진수 파이프라인을 통해 임의의 대체 GID를 생성하는 완전한 프로듀서 측 모양 파이프라인을 구축할 수 있습니다.
  • 상태 수명: 합성 매핑은 RegisterUnicodeTTF가 다시 호출되거나 BeginDoc가 실행될 때까지 유지됩니다 (둘 다 각 글꼴의 모든 상태, 합성 테이블 포함을 재설정합니다). PUA 범위 U+E000-U+F8FF는 6400개의 슬롯을 제공하며, 이는 모든 실제 글꼴의 GSUB 대체 집합에 충분합니다. ToUnicode CMap 역 매핑은 호출자의 책임입니다. 합성 PUA 코드 포인트에는 역 매핑할 소스 코드 포인트가 없으므로, 텍스트 추출에 관심이 있는 호출자는 PDF에 포함된 텍스트를 방출할 때 /ActualText 속성을 사용하여 원래 소스 코드 포인트를 지정해야 합니다. AssignSyntheticCodepointForGID를 호출하지 않는 경우, 출력은 v2.119.67과 동일한 바이트 스트림을 생성합니다 (새로운 메서드는 상태가 없는 쿼리 및 명시적 할당 도우미이며, 자동적인 부작용은 없습니다). 이 커밋은 GSUB 엔진 로드맵 8단계 기능 행렬을 완료합니다.

2026-05-22 Version 2.119.67

  • 데바나가리 재정렬 사전 적용 기능이 자동으로 실행됩니다 (GSUB 엔진 로드맵 8단계): `sfIndicShaping`이 `FShapingFeatures`에 포함된 경우, 세 개의 `BuildUnicode*FieldContent` 함수는 이제 자동으로 `v2.119.55` 버전의 `ApplyDevanagariReorder` 메서드를 호출합니다. 이 사전 적용 단계는 입력 데이터를 왼쪽에서 오른쪽으로 순회하면서, 음절 시작 부분의 '라-할란트'를 재배치하고, 'I-마트라' (U+093F)를 해당 음절 그룹의 시작 부분으로 이동시키는 두 가지 데바나가리 관련 재정렬 작업을 수행합니다. 이렇게 하면 출력되는 코드 포인트 스트림이 시각적으로 읽히는 순서와 일치합니다. 그런 다음, 사용자 측 GSUB 엔진은 재정렬된 코드 포인트에 대해 'nukt', 'akhn', 'rphf', 'rkrf', 'pref', 'half', 'vatu', 'cjct', 'pres', 'blws', 'abvs', 'psts', 'haln'으로 구성된 인디카 셰이핑 체인을 적용하여 최종 클러스터 글리프를 생성합니다.
  • 범위: 8e 단계에서는 프로듀서 측의 재정렬 기능만 제공됩니다. 프로듀서 측의 GSUB 체인 적용 기능(여기서 프로듀서는 PDF 생성 시 클러스터 모양을 결정하며, 리더가 이를 처리하는 방식에 의존하지 않습니다.)은 8c.6 단계로 연기되었습니다. 그 이유는 대부분의 데바나가리 GSUB 대체 항목이 글꼴별 GID를 사용하며, 유니코드 프리젠테이션 폼 코드를 제공하지 않기 때문입니다. 아랍어/라틴어의 경우 Forms-A/Forms-B 블록이 코드를 통해 접근 가능한 대체 항목을 제공하지만, 데바나가리에는 이에 상응하는 프리젠테이션 폼 범위가 유니코드에 존재하지 않습니다. 8c.6 단계의 PUA 합성 코드 포인트 매핑은 데바나가리 및 글꼴별 대체 GID를 사용하는 다른 인도/동남아시아 스크립트에 대한 프로듀서 측 GSUB 기능을 활성화할 것입니다.
  • 데바나가리 문자가 아닌 콘텐츠는 `ApplyDevanagariReorder` 함수를 통해 바이트 단위로 동일하게 처리됩니다 (이 함수는 데바나가리 음절만 처리하며, 다른 코드 포인트 범위는 변경되지 않고 출력됨). `sfIndicShaping` 옵션을 끄고 호출하는 경우 (기본값), PDF는 v2.119.66 버전의 출력과 바이트 단위로 동일합니다. v2.119.55 버전의 기능 레이어 ( `GetDevanagariCategory` 및 `ApplyDevanagariReorder`를 공개 메서드로 제공)와 함께, 이번 변경 사항은 데바나가리 관련 재정렬 기능을 완성합니다. 이제 `sfIndicShaping` 옵션을 활성화하는 경우, 호출자는 더 이상 `BuildUnicode*FieldContent` 함수를 호출하기 전에 별도로 재정렬하거나 `ApplyDevanagariReorder` 함수를 수동으로 호출할 필요가 없습니다. HotPDF가 자동으로 처리합니다.

2026-05-22 Version 2.119.66

  • GSUB 'rclt' (필수 문맥적 대체) 자동 통합: 새로운 THotPDF.ApplyArabicGSUBContextualRefinement (Wide) 메서드는 v2.119.63의 ApplyArabicGSUBRefinement과 유사하지만, 리간드 대체(Type 4) 대신 v2.119.47의 ApplyContextualSubst API를 통해 문맥적 치환(GSUB Type 5 / 6)을 적용합니다. 'rclt'는 필수적인 문맥 의존적 치환을 인코딩하며, 이는 일반적으로 아랍 글꼴에서 v2.85.0의 정적 분석기의 Forms-B 매핑을 넘어 추가적인 위치 변형을 제공하고, 동남아시아/인도 글꼴에서 이웃 문맥에 따라 클러스터 수준에서 모양을 재정렬하는 데 사용됩니다.
  • 가변 길이 출력 처리: `ApplyLigatureSubstitution` (N개의 입력 GID -> 1개의 대체 GID)과 달리, `ApplyContextualSubst`는 N개의 입력 GID에서 M개의 대체 GID를 생성할 수 있습니다. 컨텍스트 규칙이 적용될 때, 모든 대체 GID는 대체가 완료되기 위해 역 매핑(FB00-FDFF + FE70-FEFF, 약 770개의 코드 포인트 스캔)을 통해 Unicode Presentation Form 코드 포인트를 통해 접근 가능해야 합니다. 만약 대체 GID 중 하나라도 역 매핑이 없으면, 입력 데이터는 변경되지 않고 그대로 통과됩니다 (부분적인 출력은 시퀀스를 손상시킬 수 있습니다). 역 매핑 범위가 확장되어 라틴/아르메니아/히브리어 Presentation Form (FB00-FB4F)과 전체 아랍어 범위를 포함하게 되었으며, 이를 통해 모든 스크립트에서 'rclt' 대체가 가능해졌습니다.
  • 새로운 THPDFShapingFeature 열거형 멤버인 sfContextualAlternates가 추가되었습니다 (역호환성을 위해 뒤쪽에 추가되었으며, 기존 FShapingFeatures를 사용하는 호출자는 v2.119.59의 5개 멤버로 구성된 열거형을 변경 없이 컴파일할 수 있습니다). 이 기능은 FShapingFeatures에서 sfContextualAlternates에 의해 제어되는 세 가지 BuildUnicode*FieldContent 도우미 함수에 통합되었습니다 (옵션 기능이며, 기본적으로 비활성화되어 있습니다). FAutoShapeArabic과는 독립적으로 작동하며, 'rclt'는 아랍 스크립트가 아닌 다른 스크립트(라틴, 히브리어, 인도 문자)에도 적용될 수 있습니다. v2.84.0 서브세터에서 대체 GID는 MarkUnicodeGlyphUsed를 통해 처리됩니다. 글꼴에 'rclt' 규칙이 없거나 대체 GID에 Presentation Form 코드 포인트가 없는 경우, 안전하게 아무 작업도 수행하지 않습니다. sfContextualAlternates를 비활성화한 경우, 출력 결과는 v2.119.65와 동일한 바이트 스트림을 생성합니다.

2026-05-22 Version 2.119.65

  • Latin 'liga' 표준 연자음 기능(GSUB 엔진 로드맵 8b 단계): 새로운 THotPDF.ApplyLatinLigatureRefinement (Wide) 메서드는 v2.119.63 ApplyArabicGSUBRefinement과 유사하지만, U+FB00-U+FB4F 범위의 라틴/아르메니아/히브리어 문자 표현 형식을 대상으로 합니다. 입력 문자열을 순회하면서 FUnicodeCpToGid를 통해 병렬 GID 배열을 생성하고, 각 위치에서 v2.119.43-50 ApplyLigatureSubstitution API를 통해 글꼴의 GSUB 'liga' (표준 연자음) 기능을 쿼리합니다. 연자음 대체가 적용되고 대체 GID가 Unicode 문자 표현 형식 코드포인트를 통해 접근 가능하다면, 원본 코드포인트 범위를 대체 코드포인트로 바꿉니다. 이 기능은 FShapingFeatures의 sfStandardLigatures 설정(선택 사항, 설정하지 않으면 바이트 안정성 유지)에 따라 활성화되는 세 가지 BuildUnicode*FieldContent 도우미 함수(단일 라인, 멀티 라인, 그리고 AcroForm /AP 외관 스트림 생성기)에 통합되어 있습니다.
  • 'clig' (문맥적 리가처)에 대한 선택적 두 번째 처리: `sfContextualLigatures`가 `FShapingFeatures`에 포함된 경우, 이 메서드는 'liga' 처리 후 결과를 다시 검토하여 글꼴별 문맥적 리가처를 적용합니다. 이는 표준 fi/fl/ffi/ffl 세트 외에 추가적인 리가처를 처리합니다. 각 생성된 대체 GID는 v2.84.0 TTF 서브세터의 동작을 위해 `MarkUnicodeGlyphUsed`를 통해 전달됩니다. 역방향 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

  • GSUB 엔진 로드맵 8c.5 단계에서, 공통 코드 포인트 어드밴스 쿼리 API (THotPDF.GetCodepointAdvance (CP: Cardinal))가 새롭게 추가되었습니다. 이 메서드는 v2.76.0 버전의 /W 캐시를 노출하여, BuildUnicodeMultilineFieldContent 도우미 함수 외부에서 사용자 정의 텍스트 줄 바꿈 계산을 수행하는 클라이언트가 폰트의 hmtx 테이블에서 가져온 캐시된 cmap을 통해, 모든 코드 포인트에 대한 실제 스케일된 em 어드밴스를 쿼리할 수 있도록 합니다. v2.119.32 / v2.119.58 / v2.119.60 / v2.119.62 버전의 정적 리가처 후처리 및 v2.119.63 버전의 GID 레벨 GSUB 개선을 통해 리가처 코드 포인트 (LAM-ALEF FEF5-FEFC, YEH-HAMZA FBEA-FBFB, Allah FDF2, Bismillah FDFD, FB50-FDFF / FE70-FEFF 범위의 GSUB 대체 표현 형태)가 생성된 후, 이 메서드는 리가처 글리프의 실제 hmtx 어드밴스를 반환합니다. 일반적으로 이 값은 원본 코드 포인트 어드밴스의 합보다 작으며, 이를 통해 클라이언트의 텍스트 줄 바꿈 계산이 렌더링 결과와 일치하도록 합니다.
  • `BuildUnicodeMultilineFieldContent` 휴리스틱 폴백 개선: v2.65 버전의 폴백 경로(예: `RegisterUnicodeFontDict` 경로 대신 `RegisterUnicodeTTF` 경로를 사용할 때)에서 이전에 모든 코드 포인트(U+2E80 이상)를 와이드(1.0 em)로 처리했습니다. 아랍어 표현 형태(FB50-FBFF Forms-A 문자, FC00-FDFF Forms-A 리가처 + Quranic FDF0-FDFD, FE70-FEFF Forms-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가 성공한 후 어떤 컨텍스트에서도 안전하게 호출할 수 있습니다. 로드된 글꼴에 /W 캐시가 채워져 있고 새로운 쿼리 방법을 사용하지 않는 PDF 파일의 경우, 출력은 v2.119.63과 동일한 바이트를 생성합니다. 8c.5 단계에서는 GSUB 엔진 로드맵의 §8c 섹션에 정의된, 프로듀서 측의 자동 아랍어 GSUB 렌더링 파이프라인을 구현합니다. 8c.1부터 8c.5까지의 단계는 정적 테이블 기반의 후처리 (4개의 리가처 패밀리), ToUnicode 역매핑, GID 레벨의 GSUB 개선, 그리고 공개적인 어드밴스 쿼리를 결합하여, 프로듀서 측의 아랍어 리가처 렌더링이 소비자 측 디스플레이와 바이트 단위로 정확하게 일치하도록 합니다.

2026-05-22 Version 2.119.63

  • GID 수준의 GSUB 'rlig' 개선 후처리 (GSUB 엔진 로드맵 8c.2단계): 새로운 THotPDF.ApplyArabicGSUBRefinement (Wide) 메서드는 입력 문자열을 왼쪽에서 오른쪽으로 순회하면서 캐시된 cmap(FUnicodeCpToGid)을 사용하여 병렬 GID 배열을 생성하고, 각 0이 아닌 GID 위치에서 폰트의 GSUB 'rlig' (필수 연결 문자) 기능을 v2.119.43-50 ApplyLigatureSubstitution API를 통해 쿼리합니다. 연결 문자 대체가 발생하고 대체 GID가 Unicode 아랍어 표현 형식 코드포인트(U+FB50-U+FDFF + U+FE70-U+FEFF, 약 690개 코드포인트)를 통해 접근 가능한 경우, 원본 코드포인트 영역은 대체 코드포인트로 바뀝니다. 대체 글리프는 또한 v2.84.0 TTF 서브세터의 기능을 위해 MarkUnicodeGlyphUsed를 통해 처리됩니다.
  • v2.85.0 / v2.119.32 / v2.119.58 / v2.119.60 / v2.119.62 버전 이후의 세 가지 BuildUnicode*FieldContent 함수에 통합되었으며, 이는 정적 코드 포인트 수준의 후처리 체인(LAM-ALEF / YEH-HAMZA / Allah / Bismillah) 바로 다음에 위치합니다. 이 기능은 정적 테이블을 보완하며, 네 가지 하드 코딩된 글꼴에서 처리되지 않는 글꼴별 'rlig' 규칙을 적용합니다. 이러한 규칙은 페르시아어/우르두어/신디어/쿠르드어 글꼴(Vazirmatn, Markazi Text, Lateef, Scheherazade, Amiri)에서 흔히 볼 수 있으며, LAM-ALEF / YEH-HAMZA / Allah / Bismillah 세트에 포함되지 않는 Unicode Presentation Forms에 매핑됩니다. 이 기능은 FAutoShapeArabic가 참이고, FShapingFeatures에 sfArabicGSUB가 포함되지 않은 경우(mutex는 v2.119.59의 "호출자 주도" 경로를 유지)에만 실행되며, 로드된 글꼴에 GSUB 테이블이 있어야 합니다.
  • 범위 제한: Presentation Form 코드 포인트를 통해 cmap을 통해 GID가 도달 가능한 대체 항목만 출력됩니다. 글꼴별 GSUB 대체 항목이 임의의 글리프 ID에 위치하는 경우(역방향 코드 포인트 매핑이 없는 경우) 이 경로를 통해 출력할 수 없습니다. 이러한 대체 항목은 Phase 8c.5 이상에서 전체 GID 수준으로 출력해야 합니다. 역방향 cmap은 대체 시도당 약 690개의 코드 포인트를 선형 스캔하며, 실제로는 대체가 거의 발생하지 않으므로 비용은 무시할 수 있습니다. 로드된 글꼴에 GSUB 'rlig' 내용이 없거나 대체 항목에 Presentation Form 코드 포인트가 없는 PDF 파일은 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.
  • ToUnicode CMap이 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의 4자리 코드 포인트 소스 시퀀스를 나타냅니다. 이 업데이트를 통해 세 가지 정적 테이블 리가처 패밀리에 대한 복사/붙여넣기 및 접근성 기능이 완벽하게 구현되었습니다.
  • 아랍어 콘텐츠가 없는 경우 안정적인 동작을 제공합니다. `bfchar` 블록은 압축되지 않은 PostScript 텍스트 약 700바이트를 CMap 스트림에 추가하며, `FlateDecode`를 통해 일반적으로 약 150-200바이트로 줄어듭니다. 아랍어 콘텐츠가 없는 PDF 파일에서도 동일한 `/ToUnicode` 스트림 레이아웃을 사용합니다. 이 기능은 동일한 간접 `FlateDecode` 스트림 객체 내에서 추가적으로 적용됩니다. Adobe Reader, Foxit, PDF.js, Apple Preview 등과 같은 소비자 리더는 `bfchar`의 우선순위를 `bfrange`보다 높게 적용하며, 올바른 역 매핑을 수행합니다. 27개의 항목으로 구성된 이 블록은 CMap 텍스트에 하드 코딩되어 있으며(PDF별 사용자 정의가 필요하지 않음), 향후 8c.4 단계에서는 U+FDFD Bismillah 리가처에 대한 추가 `bfchar` 항목이 추가될 예정입니다.

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` 집합 유형은 8a부터 8e까지의 프로듀서 측 텍스트 모양 조정 통합을 위한 계획된 기능 플래그를 모델링합니다. 이 열거형에는 `sfArabicGSUB` (이번 릴리스에 구현됨), `sfStandardLigatures` (8b 단계, 향후), `sfContextualLigatures` (8b 단계, 향후), `sfStylisticAlternates` (8d 단계, 향후), 그리고 `sfIndicShaping` (8e 단계, 향후)의 다섯 가지 멤버가 있습니다. `THotPDF`는 `THPDFShapingFeatures` 유형의 `ShapingFeatures` 속성을 추가하며, 기본값은 `[]` (모든 기능 비활성화)입니다. `v2.119.32-58` 버전의 경우, 해당 속성이 기본값으로 유지되는 한, 출력 결과는 이전 버전과 동일합니다.
  • sfArabicGSUB은 v2.85.0의 정적 테이블 아랍어 셰이퍼에 대한 뮤텍스로 작동합니다. ShapingFeatures에 sfArabicGSUB이 포함된 경우, 세 개의 BuildUnicode*FieldContent 도우미(단일 라인, 멀티 라인 및 결합 AcroForm /AP 어피어런스 스트림 빌더)는 _ApplyArabicShaping을 완전히 건너니다. 즉, v2.85.0의 네 위치 코드 포인트 재작업, v2.119.32의 LAM-ALEF 후처리, v2.119.58의 YEH-HAMZA + 모음 후처리가 수행되지 않습니다. 호출자는 v2.119.43-50 GSUB 엔진 API(SetGSUBScript ('arab') + 'init' / 'medi' / 'fina' / 'isol' 기능 태그에 대한 GetSingleSubstituteGlyph + v2.84.0 서브세터에 대한 MarkUnicodeGlyphUsed)를 사용하여 아랍어 셰이프 선택을 제어해야 합니다. sfArabicGSUB과 함께 사용하면 Noto Sans Arabic / Amiri / Scheherazade / Markazi Text / 유사한 아랍어 글꼴을 사용하는 호출자는 정적 테이블 대체 방식을 사용하는 대신, 렌더링 시점에 전체 글꼴 측면 GSUB 아랍어 셰이핑을 수행할 수 있습니다.
  • Companion Arabic capability API: two new public methods GetArabicJoiningClass (CP) and GetArabicPosition (Wide, Index) mirror the v2.119.53 GetSyriacJoiningClass / v2.119.54 GetMongolianJoiningClass pattern, exposing the internal joining-class table and 4-position contextual walker the static shaper uses. Callers driving Arabic GSUB shaping manually no longer need to re-derive joining-class data per codepoint — they can reuse the cumulative v2.85.0 / v2.119.35 / v2.119.52 / v2.119.57 table that already covers basic Arabic (U+0600-U+06FF), Arabic Supplement (U+0750-U+077F), and Arabic Extended-A (U+08A0-U+08FF). With this slice landed, the user's two-item request "Forms-A FBEA-FBFB 装饰类合字 (v2.119.58) + Producer-side 自动 Arabic GSUB shaping pipeline (this release)" is fulfilled at the capability + opt-in framework layer. Full producer-side automatic GSUB application inside TextOut / BuildUnicode*FieldContent (auto cmap-to-GID + per-position GSUB substitute + substitute GID emit, with no caller code) remains reserved for the deeper Phase 8c integration commits.

2026-05-22 Version 2.119.58

  • YEH-HAMZA + 모음-문자 결합 후처리: v2.85.0 버전의 아랍어 셰이퍼는 아랍어 프레젠테이션 폼-A 블록의 U+FBEA-U+FBFB 범위에 있는 8개의 결합 쌍을 4자리 워커 및 v2.119.32 LAM-ALEF 후처리 단계에서 단일 결합 코드 포인트로 통합합니다. 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)로 일치합니다. 다음의 모음 문자는 원본 형태 또는 v2.119.57에서 정의된 Forms-A 형태(U의 경우 FBD7-FBD8, OE의 경우 FBDB-FBDC, YU의 경우 FBDB-FBDC, E의 경우 FBE4-FBE7) 또는 v2.85.0에서 정의된 Forms-B 형태(ALEF의 경우 FE8D-FE8E, WAW의 경우 FEED-FEEE, ALEF MAKSURA의 경우 FEEF-FEF0)로 일치합니다. 최종 형태 선택(기본 + 1)은 LAM-ALEF 규칙을 따릅니다. 즉, YEH-HAMZA가 FE8A final 또는 FE8C medial 형태로 변환되었거나(즉, 이중 결합 문자로 시작하는 경우), 리가처는 최종 형태로 출력됩니다. 그렇지 않으면 분리된 형태로 출력됩니다.
  • 이 후처리 단계에서는 격리된 최종 형태(2형식 출력)만 생성됩니다. Unicode에서 정의한 초기 형태인 FBF8 (YEH-HAMZA + E) 및 FBFB (위구르 YEH-HAMZA + ALEF MAKSURA)는 생성되지 않습니다. 이러한 세 가지 형태의 변형이 필요한 사용자는 ApplyContextualSubst를 통해 글꼴의 'rlig' / 'clig' 체인 컨텍스트 GSUB 조회를 수행해야 합니다. 다른 아랍어 연결 문자 영역(Allah U+FDFA / FDFB, FC00-FDC7의 장식 연결 문자)은 GSUB 'rlig' / 'dlig'를 사용해야 하며, 이 범위는 정적 테이블 셰이퍼의 대상이 아닙니다. YEH-HAMZA 다음에 지원되는 여덟 가지 모음 문자 중 하나가 오는 PDF 파일은 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개는 U+FB52-U+FBFC 범위에서 정적 프레젠테이션 폼-A 항목을 가지고 있으며, 이제 글꼴 GSUB 셰이퍼가 필요 없이 정적 테이블 셰이퍼에 의해 직접 매핑됩니다. 여기에는 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)가 포함됩니다.
  • 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 범위의 글자 중 Unicode 16에서 Presentation Forms-A 항목이 없는 글자(약 50개의 추가 코드 포인트, 주로 사전 인코딩된 모양이 없는 REH/DAL/SEEN/SAD/TAH/AIN/FEH/QAF/KAF 변형)는 여전히 조인 클래스 분석에 참여하므로 인접 글자가 올바르게 모양을 갖습니다. 이러한 글자 자체는 원시 코드 포인트로 처리되며 자체 모양 선택을 위해 v2.119.43-50 GSUB 엔진에서 글꼴의 GSUB 조회 테이블에 의존합니다. 78018 라인으로 컴파일되었으며, 이러한 새로운 코드 포인트가 없는 PDF 파일은 v2.119.56 버전과 동일한 바이트를 출력합니다.

2026-05-22 Version 2.119.56

  • 아랍어 모양 관련 버그 수정: v2.119.52 버전에서 두 개의 우르두어/신드히어 지역 문자(U+06C2 HEH GOAL WITH HAMZA ABOVE 및 U+06C3 TEH MARBUTA GOAL)에 대한 잘못된 아랍어 프레젠테이션 폼-A 매핑이 도입되었습니다. U+06C2 HEH GOAL WITH HAMZA ABOVE는 FBAA-FBAD로 매핑되었지만, 이는 실제로 U+06BE HEH DOACHASHMEE의 코드 포인트 범위입니다. 따라서 사용자 뷰어는 우르두어 "Goal-Heh-with-Hamza" 글리프를 표준 우르두어 "Heh-Doachashmee" 글리프 대신 렌더링했습니다. U+06C3 TEH MARBUTA GOAL은 FBAE-FBAF로 매핑되었지만, 이는 실제로 U+06D2 YEH BARREE의 코드 포인트 범위입니다. 따라서 뷰어는 "Teh-Marbuta-Goal"을 우르두어 단어의 마지막 글자인 "Yeh-Barree"로 렌더링했습니다. Unicode 16.0에 따르면 U+06C2와 U+06C3 모두에 대해 미리 인코딩된 프레젠테이션 폼-A 항목이 없으며, 두 문자 모두 변경 없이 원시 코드 포인트로 전달되어야 합니다(사용자 뷰어는 글꼴의 cmap 및 GSUB 기반 모양 기능을 통해 이를 올바르게 표시합니다).
  • 수정 사항: v2.85.0 버전의 아랍어 셰이퍼에서 _ArabicShape Presentation Forms-A_ 조회 테이블에 있던 두 가지 잘못된 항목이 제거되었습니다. U+06C2 및 U+06C3은 이제 기본 경로로 전달되어 변경되지 않은 상태로 출력됩니다. v2.119.52 버전에서 도입된 연결 클래스 항목(U+06C2에 대한 D, U+06C3에 대한 R)은 유지되어, 이러한 문자가 단어 내에 있을 때 인접한 문자가 올바른 위치 정보를 사용하도록 합니다. 이 수정 사항은 AutoShapeArabic이 활성화된 U+06C2 또는 U+06C3을 포함하는 PDF 파일에만 영향을 미치며, 해당 두 코드 포인트를 포함하지 않는 PDF 파일은 v2.119.55 버전의 출력과 동일합니다. 함께 배포되는 v2.119.57 버전은 Forms-A 지원 범위를 추가적인 페르시아어/우르두어/신드어/카슈미르어/위구르어/카자흐어/키르기스어 문자로 확장합니다. 여기에는 v2.119.52 버전의 오류로 인해 혼동되었던 HEH DOACHASHMEE 및 YEH BARREE와 같은 진정으로 Forms-A로 인코딩된 문자도 포함됩니다.

2026-05-22 Version 2.119.55

  • 데바나가리 문자 형태 지정 기능: THotPDF 클래스에 두 개의 새로운 공개 메서드가 추가되어 데바나가리 문자 형태 지정 방식을 지원합니다. 이 방식은 아랍어/시리아어/몽골어에서 사용되는 4자리 결합 클래스 탐색기와 호환되지 않습니다 (v2.85.0 + v2.119.32-54). GetDevanagariCategory (CP) 메서드는 Unicode 16.0 §12.1 및 IndicSyllabicCategory.txt에 정의된 간략화된 데바나가리 음절 범주를 반환합니다 (0 = 기타, 1 = 자음, 2 = 독립 모음, 3 = 마트라, 4 = 비라마, 5 = 누크타, 6 = 빈두, 7 = 비사르가, 8 = 단다, 9 = 숫자, 10 = ZWJ, 11 = ZWNJ, 12 = 수정자). 이 표는 U+0900-U+097F 범위의 전체 데바나가리 문자 집합을 포함하며, U+0978-U+097F 범위의 마와리/신드히/베딕 확장 문자도 포함합니다.
  • ApplyDevanagariReorder (Wide) 함수는 입력 문자열을 왼쪽에서 오른쪽으로 순회하며, 발견되는 모든 데바나가리 음절에 대해 데바나가리 재정렬 전처리 단계를 적용합니다. 이렇게 재정렬된 UnicodeString은 cmap 및 GSUB 처리에 적합한 상태로 반환됩니다. 데바나가리 문자가 아닌 콘텐츠(라틴 문자, 숫자, 구두점, 기타 문자)는 변경 없이 그대로 통과됩니다. 구현된 재정렬 방식은 실제 데바나가리 문자 모양에서 가장 흔하게 사용되는 두 가지 방식입니다. (1) Repha: 음절이 Ra (U+0930) + Halant (U+094D) + 자음으로 시작하는 경우, (Ra, Halant) 쌍을 음절의 끝으로 이동시키고, 글꼴의 'rphf' GSUB 기능을 사용하여 해당 음절의 기본 글자에 시각적으로 연결되는 Repha 글리프를 대체합니다. (2) Pre-base I-matra: U+093F 문자를 음절의 맨 앞에 이동시킵니다 (Repha 제거 후). 이렇게 하면 왼쪽에서 오른쪽으로 처리하는 GSUB 프로세스에서 해당 문자가 자음 클러스터 앞에 위치하게 되어, 시각적 렌더링 순서와 일치합니다.
  • 호출 파이프라인: 논리적 순서의 텍스트에 `ApplyDevanagariReorder`를 적용 -> `SetGSUBScript('deva')` 설정 -> 재정렬된 코드 포인트를 순회하면서 `GetSingleSubstituteGlyph` 및 `ApplyLigatureSubstitution` + `ApplyContextualSubst`를 사용하여 `GSUB` 기능('nukt' / 'akhn' / 'rphf' / 'rkrf' / 'half' / 'vatu' / 'cjct' / 'pres' / 'blws' / 'abvs' / 'psts' / 'haln')을 적용 -> `MarkUnicodeGlyphUsed(GID)`를 호출하여 생성된 `GID`를 PDF 텍스트 스트림으로 출력 (v2.84.0 서브세터). A 단계 (v2.119.52 아랍 확장-A) + B 단계 (v2.119.53 시리아 기능) + C 단계 (v2.119.54 몽골 기능) + D 단계 (v2.119.55 데바나가리 인도 기능)가 모두 완료되었으므로 "몽골 / 시리아 / 데바나가리 텍스트 모양" 관련 격차가 완전히 해소되었습니다. 적용 범위에서 제외되는 항목: 데바나가리 이외의 인도 문자 (벵골어, 타밀어, 텔루구어, 구자라트어 - 각 문자에는 자체 카테고리 데이터 및 재정렬 규칙이 있음), Repha를 넘어서는 재정렬 규칙, 그리고 `TextOut` / `BuildUnicode*FieldContent` 내에서의 프로듀서 측 자동 데바나가리 텍스트 모양 (GSUB 엔진 로드맵의 8단계에서 예약).

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 기반 인덱스에 있는 문자에 대해 0 = 고립, 1 = 최종, 2 = 초기, 또는 3 = 중간 값을 반환합니다.
  • 시리아어와 마찬가지로, 몽골어는 유니코드에 사전 인코딩된 프리젠테이션 형식이 없습니다. 몽골어 기능을 지원하는 모든 글꼴(몽골어 바이티, Noto Sans 몽골어, Noto Serif 몽골어 등)은 OpenType GSUB 조회를 통해 위치 기반 서식을 제공하며, 이는 'init', 'medi', 'fina', 'isol' 기능과 'mong' 스크립트 태그 아래에서 작동합니다. 따라서 v2.119.54는 v2.119.53과 동일한 기능 중심 모델을 따릅니다. 호출자는 v2.119.43-50 GSUB 엔진 API(SetGSUBScript('mong'), 해당 위치 기능 태그에 대한 GetSingleSubstituteGlyph, v2.84.0 서브세터에 대한 MarkUnicodeGlyphUsed)를 사용하여 위치 정보를 구성하고, 이를 통해 서식이 적용된 GID를 생성하여 PDF 텍스트 스트림에 직접 출력합니다.
  • 몽골어는 기본 글꼴 모드에서 위에서 아래로 수직으로 작성됩니다. 이 기능은 논리적인 코드 포인트 순서(코드 포인트 스트림 내의 이전/다음)로 작동하며, 시각적 방향에 관계없이 작동합니다. 실제 위에서 아래로 렌더링은 PDF 생성 시 /WMode 1(수직 쓰기) 또는 글꼴 매트릭스 회전을 통해 처리되며, 셰이퍼에서 처리하지 않습니다. Free Variation Selectors(FVS)의 투명 분류는 이 기능이 FVS가 문자의 뒤에 오는 경우에도 위치 정보를 올바르게 처리하도록 합니다. 글꼴의 GSUB 테이블에서 'fina', 'medi', 'init', 'isol' 기능에 해당하는 항목을 사용하여, 입력 스트림에 FVS가 포함된 경우 자동으로 FVS에 따른 변형을 선택합니다. 데바나가리(인도) 셰이핑은 UAX #38에 따른 인도 문자 재정렬 전처리 과정이 필요하기 때문에 향후 버전에서 구현될 예정입니다. 자동 몽골어 셰이핑은 TextOut / BuildUnicode*FieldContent 내에서 GSUB 엔진 로드맵의 8단계에서 구현될 예정입니다.

2026-05-22 Version 2.119.53

  • 시리아 문자 모양 기능: THotPDF 클래스에 두 개의 새로운 공개 메서드가 추가되어 시리아 문자(U+0700-U+074F)의 결합 클래스 조회를 지원하고, 4위치 문맥 분석을 제공하여 호출자가 시리아 텍스트의 모양을 생성하는 데 사용할 수 있습니다. GetSyriacJoiningClass(CP)는 Unicode 16.0의 SyriacShaping.txt 결합 클래스(0 = 결합되지 않음, 1 = 오른쪽 결합, 2 = 양방향 결합, 4 = 투명 / NSM)를 반환하며, 이는 모든 코드 포인트에 대해 적용됩니다. 이 테이블은 기본 블록의 35개 시리아 문자와 함께 페르시아 및 소그디아 확장(U+072D-U+072F의 페르시아 BHETH / GHAMAL / DHALATH, U+074D-U+074F의 소그디아 ZHAIN / KHAPH / FE)를 포함하며, SUPERSCRIPT ALAPH(U+0711)와 시리아 결합 부호(U+0730-U+074A)를 투명으로 분류합니다. GetSyriacPosition(Wide, Index)은 주변 텍스트를 탐색하면서 투명 부호를 건너뛰고, 0-based Index의 문자에 대해 0 = 고립, 1 = 최종, 2 = 초기, 또는 3 = 중간 값을 반환합니다.
  • 아랍어와 달리(아랍어는 미리 인코딩된 Presentation Forms-B (U+FE70-U+FEFF) 및 Forms-A (U+FB50-U+FBFF) 블록을 가지고 있어 HotPDF가 직접 코드 포인트를 모양이 있는 변형으로 다시 쓰도록 허용합니다), 시리아어 블록에는 Unicode에서 미리 인코딩된 프레젠테이션 형식이 없습니다. 시리아어를 지원하는 모든 글꼴(Estrangelo Edessa, Serto Jerusalem, East Syriac Adiabene, Noto Sans Syriac 등)은 OpenType GSUB 조회를 통해 위치 기반 모양을 구현하며, 이는 'init' / 'medi' / 'fina' / 'isol' 기능에서 수행됩니다. 따라서 v2.119.53은 기능 레이어만 제공하며, 호출자는 v2.119.43-50 GSUB 엔진 API(SetGSUBScript ('syrc'), 해당 위치 기능 태그에 대한 GetSingleSubstituteGlyph, v2.84.0 서브세터에 대한 MarkUnicodeGlyphUsed)를 사용하여 위치 정보를 결합하여 모양이 있는 GID를 생성하고, 이를 PDF 텍스트 스트림으로 직접 출력합니다.
  • 알랍 터미널 형태 범위: Unicode §9.3에서는 문맥적 터미널 기능 두 가지('DALATH/RISH 뒤에 'fin2' 적용, 'FINAL LAMADH' 뒤에 'fin3' 적용)를 설명하며, 시리아 글꼴이 알랍의 최종 글리프를 교체하는 데 사용합니다. v2.119.53에서는 알랍(U+0710)을 기본 오른쪽 결합 문자로 분류하고, 'fin2'/'fin3'의 차이를 필요로 하는 호출자는 해당 기능 태그를 사용하여 글꼴의 체인형 문맥 대체 기능을 활성화해야 합니다. 몽골어 및 데바나가리(인도) 형태 지정은 향후 버전에서 구현될 예정입니다. 몽골어는 자유 변형 선택기와 모음 조화를 사용하며, 데바나가리는 UAX #38에 따른 인도어 재정렬 전처리 과정을 필요로 합니다. 이 두 가지는 시리아 스타일의 4위치 탐색기에 매핑되지 않습니다. TextOut / BuildUnicode*FieldContent 내의 자동 시리아 형태 지정은 GSUB 엔진 로드맵의 8단계에서 구현될 예정입니다.

2026-05-22 Version 2.119.52

  • 아랍어 문자 모양 확장: v2.85.0 버전에서 아랍어 렌더링 엔진은 이제 아랍어 확장-A에 남아 있는 문자(ALEF WASLA U+0671, NOON GHUNNA U+06BA, HEH 변형 U+06C0-U+06C3), 아랍어 보충 블록 U+0750-U+077F(하우사어, 울로팔 및 기타 아프리카 언어에 사용되는 아프리카 아랍어 문자), 그리고 새로운 아랍어 확장-A 지역 U+08A0-U+08FF(코란 아랍어 + 울로팔/하우사어 확장 문자 + 코란 결합 부호)를 지원합니다. 조인 클래스는 Unicode 16.0의 ArabicShaping.txt에서 가져와 v2.85.0 버전의 4단계 위치 분석 과정에서 적용되므로, 인접한 문자가 어떤 아랍어 변형인지에 관계없이 올바른 init/medi/fina/isol 형태를 선택합니다.
  • 아랍어 프레젠테이션 폼-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(오른쪽 결합, 두 가지 형식)로 매핑됩니다. 또한 v2.119.32 버전의 LAM-ALEF 필수 리가처 후처리 및 v2.119.35 버전의 페르시아어/우르두어 핵심 9자 문자 세트와 함께, 이 정적 셰이퍼는 이제 글꼴의 GSUB 테이블에 의존하지 않고 현대 아랍어, 페르시아어, 우르두어, 신드히어, 파슈투어, 쿠르드어, 위구르어, 꾸란어 및 아프리카 아랍어(하우사어, 울로팔어 등) 텍스트를 거의 완벽하게 지원합니다.
  • 아랍어 보충 문자(U+0750-U+077F) 및 최신 아랍어 확장 문자 A 영역(U+08A0-U+08C7)에는 사전 인코딩된 정적 표현 형식이 없습니다. 이 문자들의 연결 클래스 항목은 주변 문자가 올바르게 모양을 갖도록 하지만, 문자 자체는 원시 코드 포인트로 유지되며 자체 위치 조정에는 GSUB을 지원하는 글꼴(또는 호출자가 사용하는 v2.119.43-50 GSUB 엔진 API)에 의존합니다. 아랍어 확장 문자 A의 꾸란 결합 문자 영역(U+08CA-U+08E1, U+08E3-U+08FF)은 투명(T-연결)으로 분류되므로 주변 문자 위치 분석에서 제외되며, 이는 기존 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은 정적 /Fields 배열과 함께 또는 대신 /XFA 항목을 포함할 수 있습니다. 새로운 THotPDF.AddXFAPacket(PacketName, XMLBytes) 함수는 지정된 이름의 XFA 패킷을 등록합니다. 일반적인 이름으로는 'template'(폼 레이아웃 및 스크립트), 'datasets'(데이터 바인딩), 'config'(뷰어 구성), 'connectionSet', 'localeSet', 'stylesheet', 'xfdf', 'xmpmeta', 'signature' 및 'sourceSet' 등이 있습니다. 등록된 각 패킷은 EndDoc에서 FlateDecode로 압축된 스트림으로 저장되며, /XFA 배열은 등록 순서대로 패킷 이름(PDF 문자열)과 스트림 참조를 번갈아 가며 포함하여, 레이아웃이 바이트 단위로 결정적으로 유지됩니다. THotPDF.ClearXFAPackets 및 THotPDF.XFAPacketCount 함수는 API 기능을 완성합니다.
  • HotPDF는 컨테이너 수준의 지원만 제공하며, XFA XML을 파싱하지 않고, XFA 동적 레이아웃 엔진을 구현하지 않으며, XFA 템플릿 내의 FormCalc 또는 JavaScript를 실행하지 않으며, 템플릿 구조를 검증하지 않습니다. 호출자는 XFA XML을 직접 작성합니다 (일반적으로 Adobe LiveCycle Designer를 사용하거나 XFA 3.3 사양에 따라 직접 작성). HotPDF는 작성된 바이트를 그대로 출력합니다. XFA 엔진을 탑재한 뷰어 (구형 Acrobat / Reader, FormsCentral, 일부 키오스크 제품)는 폼을 렌더링합니다. XFA 엔진이 없는 뷰어 (2017년 이후의 Adobe Reader DC, 대부분의 오픈 소스 뷰어)는 문서가 하이브리드 AcroForm + XFA 워크플로우인 경우 대체 AcroForm 필드를 표시합니다.
  • 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`가 비어 있지 않고 관련 규격 참조가 있는 경우 즉시 오류를 발생시킵니다. 중복된 패킷 이름이 있으면 오류가 발생합니다. `PacketName`이 비어 있거나 `XMLBytes`가 비어 있으면 오류가 발생합니다. `RequirePDFVersion(pdf15)`는 문서 버전을 자동으로 높입니다. 이제 `/Fields` 항목이 하나 이상 있거나 XFA 패킷이 하나 이상 등록된 경우 `AcroForm` 딕셔너리가 생성됩니다. v2.119.51 이전 버전에서 패킷을 등록하지 않은 경우에도 바이트 단위로 동일한 `/AcroForm` 출력이 유지됩니다.

2026-05-22 Version 2.119.50

  • TTF 서브세터에서 GSUB 대체 글리프에 대한 변경 사항: 새로운 THotPDF.MarkUnicodeGlyphUsed (GID: Word) 함수는 cmap에 해당 글리프에 해당하는 코드 포인트가 있든 없든, v2.84.0 EndDoc 서브세터에 글리프를 포함시킵니다. v2.84.0 버전의 서브세터는 FUnicodeUsedCps를 통해 cmap에서 사용된 글리프 집합을 가져오므로, 이전에 GSUB에 의해 도입된 모든 대체 글리프(스타일 변형, 리가처, 문맥 변형, Phase 1-6 쿼리 API의 전체 출력)는 서브세터에 의해 인식되지 않았고, 렌더링 시에는 .notdef로 표시되었습니다. 이제 GetSingleSubstituteGlyph / GetMultipleSubstituteGlyphs / GetAlternateGlyph / ApplyLigatureSubstitution / ApplyContextualSubst / ApplyReverseChainedContextualSubst를 통해 반환된 모든 GID가 PDF 텍스트 스트림에 출력되면, 호출자는 해당 GID에 대해 한 번씩 MarkUnicodeGlyphUsed (GID) 함수를 호출하여 해당 글리프를 포함된 서브세트에 추가합니다.
  • 이 도구는멱등성을 갖습니다 (동일한 GID로 반복적으로 호출해도 아무런 영향이 없음), 안전합니다 (GID가 FUnicodeNumGlyphs보다 크면 자동으로 무시되며, RegisterUnicodeTTF 호출 전에 이루어지는 호출은 무효화됨), 그리고 _BuildSubsetTTF 내부의 v2.84.0 복합 글리프 처리 과정과 통합됩니다. 호출자는 최상위 대체 GID만 지정하면 되며, 복합 구성 요소는 기존의 _TTFWalkCompositeClosure 함수에 의해 자동으로 처리됩니다. 이 집합은 처음 호출될 때 할당되며, RegisterUnicodeTTF 함수가 호출될 때마다 (빈 값으로) 초기화되고, 서브셋 상태의 다른 부분도 함께 초기화됩니다. 이제 Phase 9가 적용되었으므로, Phase 1-7의 모든 GSUB 쿼리 API를 서브셋 생성과 함께 안전하게 사용할 수 있으며, 대체 글리프가 임베디드 글꼴에서 누락되는 문제를 방지할 수 있습니다.

2026-05-22 Version 2.119.49

  • OpenType GSUB 스크립트/언어 시스템 선택 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)`는 주어진 스크립트 아래의 모든 언어 태그를 반환하며, 스크립트에 기본 `LangSys`가 있는 경우 인덱스 0에 '' 자리 표시자가 있습니다. `GetGSUBFeatures(ScriptTag, LangTag)`는 `LangSys`의 `featureIndices` 순서대로 (스크립트, 언어) 경로에서 광고하는 모든 기능 태그(예: 'liga', 'salt', 'aalt', 'ss01' ~ 'ss20')를 반환합니다. 빈 `ScriptTag` / `LangTag`는 대체 API와 동일한 DFLT-우선 / 기본 `LangSys` 폴백을 사용하므로, 호출자는 스크립트 목록을 먼저 검사하지 않고도 `GetGSUBFeatures('', '')`를 호출하여 기본 경로의 기능을 열거할 수 있습니다.
  • 엄격한 우선순위 및 대체 선택 방식: `SetGSUBScript`가 폰트에서 광고하지 않는 태그로 설정되면, 후속 GSUB 쿼리는 빈 결과 또는 아무런 동작도 수행하지 않습니다. 엔진은 자동으로 대체 방식을 사용하지 않으므로, 호출자는 선택한 스크립트가 사용할 수 없는 경우를 명확하게 알 수 있습니다. `SetGSUBLanguage`가 인식되지 않는 태그로 설정되면, OpenType 사양 권장 사항에 따라 해당 스크립트의 기본 `LangSys`로 대체됩니다. 기존의 7가지 GSUB 대체 방법(`GetSingleSubstituteGlyph`, `GetMultipleSubstituteGlyphs`, `GetAlternateGlyphCount`, `GetAlternateGlyph`, `ApplyLigatureSubstitution`, `ApplyContextualSubst`, `ApplyReverseChainedContextualSubst`)은 공개 인터페이스가 그대로 유지됩니다. 내부 `_GSUBFindFeatureLookups` 도우미 함수는 두 개의 추가 매개변수를 가지게 되었으며, 이 매개변수는 이제 7개의 호출 지점 모두에서 사용됩니다. `Script` / `LangSys` API 및 LookupType 1-8 행렬이 구현됨에 따라, GSUB 엔진은 기능적으로 완벽하며, 기능만 사용하는 데 적합합니다. 나머지 로드맵 단계(자동 모양 생성 파이프라인 + TTF 서브세터)는 새로운 쿼리 인터페이스가 아닌, 제작 측면의 통합을 목표로 합니다.

2026-05-22 Version 2.119.48

  • OpenType GSUB 역방향 체인 컨텍스트 단일 치환 (LookupType 8): 새로운 THotPDF.ApplyReverseChainedContextualSubst (const InputGIDs; StartIndex; FeatureTag; out OutGID): Boolean이 마지막 GSUB 조회 유형으로 추가되었습니다. Type 8은 컨텍스트를 고려한 1:1 단일 치환을 수행하며, 치환되는 글리프는 입력 글리프의 Coverage 인덱스에 의해 선택됩니다. 중요한 특징은 호출자가 여러 글리프 시퀀스에 대해 역방향 스캔 순서(끝에서 시작)로 적용해야 한다는 것입니다. 이는 각 치환이 아직 치환되지 않은 미래의 컨텍스트에 의존할 수 있기 때문입니다. 이 기능은 단일 지점 적용 기능을 제공하며, 호출자가 역방향 스캔 루프를 제어합니다. Coverage Format 1 + 2, LookupFlag (입력, 백트래킹, 미리보기 모두 skip-aware), 그리고 Extension 래핑 (LookupType 7)이 모두 지원됩니다.
  • 일반적인 사용 사례는 특정 아랍어/시리아어/N'Ko/인도어 문맥 대체 글리프에 대한 것입니다. 이러한 글리프의 최종 형태는 뒤따르는 글리프의 특정 모양에 따라 달라집니다. 일부 글꼴은 이를 라틴 문자 시퀀스 구분에 사용하기도 합니다. LookupType 5/6과 달리, Type 8은 중첩된 검색 기능을 사용하지 않습니다. 왜냐하면 치환은 본질적으로 1:1 관계이기 때문입니다. 일치하는 항목이 없으면 False를 반환하며, OutGID는 InputGIDs[StartIndex]와 동일합니다(v2.119.43 GetSingleSubstituteGlyph 계약과 일치하는 최선의 결과를 제공합니다).
  • v2.119.48 버전에서 LookupType 행렬을 닫습니다. 모든 OpenType GSUB LookupType(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 (백트랙/입력/선행 컨텍스트)을 모두 포괄하며, 모든 세 가지 서브테이블 형식에 적용됩니다. 여기에는 Format 1 (문자 ID 시퀀스), Format 2 (ClassDef 클래스 시퀀스) 및 Format 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[] 인덱스를 추적하여, 이전 다중 치환이 1→N으로 확장되거나 리가처 치환이 N→1 글리프를 축소시키는 경우에도 후속 SequenceLookupRecord 항목들이 올바른 작업 위치를 계속 참조하도록 합니다. 중첩 LookupType 5 / 6 / 8 (재귀적 컨텍스트)은 의도적으로 지연됩니다. 대부분의 실제 글꼴은 중첩 검색을 Type 1 / 4에 연결합니다.
  • 일치하는 경우, 이 메서드는 True를 반환하며, InputGIDs[StartIndex..StartIndex+ConsumedLen-1]을 대체할 출력 글리프 시퀀스를 함께 반환합니다. OutGIDs의 길이는 중첩된 1→N 또는 N→1 검색이 실행될 때 ConsumedLen과 다를 수 있습니다. 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 확장 검색 테이블(LookupType 7): GSUB 엔진이 이제 확장 대체 하위 테이블을 투명하게 언패킹합니다. 이는 OpenType 사양이 매우 큰 글꼴의 실제 대체 하위 테이블이 LookupList의 Offset16의 16비트 제한 범위를 벗어나는 경우를 위해 정의한 순수한 간접 레이어입니다. 모든 v2.119.43-45 공개 API(GetSingleSubstituteGlyph / GetMultipleSubstituteGlyphs / GetAlternateGlyphCount / GetAlternateGlyph / ApplyLigatureSubstitution)는 실제 LookupType 1 / 2 / 3 / 4 하위 테이블로의 32비트 Offset32 간접 참조를 자동으로 사용합니다. 이 이진 레이아웃 변경 사항은 크기가 64KB를 초과하고 LookupType 7 래퍼 뒤에 검색 테이블을 가지고 있는 대규모 CJK/Indic OpenType 글꼴(Noto Sans CJK, Noto Sans Devanagari 등)의 사용을 가능하게 합니다. 이전에 이러한 글꼴은 HotPDF에서 기능이 없는 것처럼 보였습니다.
  • OpenType GDEF(글리프 정의) 테이블 파싱: RegisterUnicodeTTF는 이제 GDEF 테이블이 있는 경우 해당 테이블을 캐싱합니다. 세 개의 GDEF 하위 테이블이 LookupFlag 동작 논리를 제어합니다. GlyphClassDef는 각 GID를 기본(1), 이응(2), 첨자(3), 구성 요소(4)로 분류합니다. MarkAttachClassDef는 모든 첨자 글리프에 첨자 클래스 태그를 지정합니다. MarkGlyphSetsDef(v1.2 이상)은 명명된 첨자 글리프 세트를 선언합니다. ClassDef 형식 1(startGlyphID + classValueArray)과 형식 2(정렬된 classRangeRecords) 모두 구현되었습니다. GDEF v1.0 / v1.1 / v1.2 헤더가 모두 허용되며(v1.3의 itemVariationStore는 무시됨), GDEF 테이블이 없는 글꼴은 v2.119.43-45의 기본 동작("어떤 글리프도 무시되지 않음")으로 되돌아가므로, GDEF가 없는 글꼴을 사용하는 호출자에게는 바이트 단위로 동일한 출력이 유지됩니다.
  • OpenType GSUB LookupFlag을 준수합니다. 이제 모든 공개 GSUB API는 각 Lookup 테이블의 LookupFlag(그리고 LookupFlag.useMarkFilteringSet이 설정된 경우 선택적 후행 markFilteringSet uint16)를 읽고, 무시하도록 플래그가 지정된 입력 글리프를 건너니다. 사양에 정의된 플래그 비트는 다음과 같습니다. 0x0002는 ignoreBaseGlyphs(GDEF.GlyphClassDef 클래스 1을 건너끕니다), 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 lookup의 경우 여전히 무시됩니다.
  • 동일한 보안 규칙이 계속 적용됩니다. GSUB 테이블이 없는 글꼴, 4바이트가 아닌 태그를 전달하는 호출자, 글꼴의 DFLT 스크립트에서 광고하지 않는 기능, 하위 테이블이 없는 GID, 그리고 이제 LookupFlag를 무시하는 입력 글리프는 모두 v2.119.43-45 버전의 안전한 무작업 결과를 반환합니다. 다섯 가지 공개 API의 시그니처는 바이트 단위로 안정적이며, 내부 검색 과정에서만 확장 기능 처리, LookupFlag 준수 및 GDEF 분류가 적용됩니다. 스크립트/언어 시스템 선택 API, 자동 모양 파이프라인 통합, 그리고 TTF 서브세터에서 대체 글리프를 자동으로 가져오는 기능은 향후 버전에 적용될 예정입니다.

2026-05-22 Version 2.119.45

  • OpenType GSUB 리가처 대체 (LookupType 4): 새로운 THotPDF.ApplyLigatureSubstitution (const InputGIDs: Word 배열; StartIndex; FeatureTag; out OutGID; out ConsumedCount): Boolean 함수는 여러 글리프 구성 시퀀스를 단일 리가처 글리프로 결합합니다. 일반적인 사용자는 'liga' (표준 리가처 - fi / fl / ffi / ffl), 'clig' (문맥 리가처), 'dlig' (선택적 리가처), 'hlig' (역사적 리가처), 'rlig' (필수 리가처 - 글꼴이 GSUB를 통해 모양을 결정할 때 아랍어 LAM-ALEF 및 유사한 경우) 및 Indic 스크립트 리가처 기능 ('akhn', 'pres', 'blws', 'psts')입니다. 호출자는 post-cmap 글리프 ID 시퀀스와 0부터 시작하는 위치를 전달합니다. 완전한 일치가 발견되면 이 함수는 True를 반환하고, OutGID는 리가처 대체 글리프이고, ConsumedCount는 소비된 입력 구성 요소의 총 개수입니다 (실제로는 >= 2). 일치하는 항목이 없으면 False를 반환하고, OutGID는 0이고, ConsumedCount는 1이므로 호출자는 한 단계 앞으로 이동하여 계속 검색할 수 있습니다. 이 구현은 일반적으로 리가처 세트 항목이 가장 긴 것부터 나열되는 OpenType 규칙을 준수하며, 겹치는 접두사를 가진 글꼴 (예: 세 구성 요소 '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) 함수는 하나의 입력 글리프를 치환 글리프 시퀀스로 반환합니다. 이 함수의 주요 사용자는 'ccmp' 글리프 조합/분해 기능으로, 미리 조합된 악센트가 있는 라틴 문자들을 기본 글자와 결합 기호로 분리하여 후속 기호 위치 조정을 용이하게 합니다. 이 함수는 v2.119.43 버전의 GetSingleSubstituteGlyph 함수와 동일한 DFLT 스크립트/기본 언어 시스템/기능 목록/검색 목록 경로를 따라가며, 요청된 기능에 연결된 모든 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' (모든 대체 사용), 'salt' (스타일 대체), 'titl' (제목 대체) 및 'ss01'부터 'ss20'까지 (스타일 세트 1-20)이며, LookupType 3과 함께 사용하면 LookupType 1 대신 사용할 수 있습니다. 이전 버전(v2.119.43)에서는 `GetSingleSubstituteGlyph`가 이러한 서브 테이블을 무시했기 때문에, 'aalt'를 사용하는 경우 이전에는 LookupType 1의 대체만 표시되었습니다. 이 두 메서드를 사용하면 장식 글리프 순환 (다양한 'a' / 'g' / '7' 모양), 제목 글꼴 변형 및 스타일 세트 대체 사항을 명시적으로 사용할 수 있습니다. 범위를 벗어나거나 음수 `AlternateIndex` 값이 전달되면 `InputGID`가 변경되지 않고 반환되므로, 안전하게 테스트할 수 있습니다.
  • v2.119.43과 동일한 안전 장치를 모두 적용합니다. GSUB 테이블이 없는 글꼴, 4바이트가 아닌 태그를 전달하는 호출자, 글꼴의 DFLT 스크립트에서 광고하지 않는 기능, 그리고 LookupType 2/3 하위 테이블이 모든 GID를 포함하지 않는 경우, 안전한 무효 작업(Multiple의 경우 False + 빈 OutGIDs, Alternate의 경우 0 / InputGID)을 반환합니다. 기능의 Lookup 체인에서 발견되는 LookupType 1/4-8 하위 테이블은 이 버전에서는 무시됩니다. LookupFlag 마크 필터링, GDEF GlyphClassDef 통합, 스크립트/LangSys 선택 API, 자동 모양 파이프라인 통합, 그리고 TTF 서브세터에서 선택된 대체 글리프를 자동으로 가져오는 기능은 향후 버전에서 구현될 예정입니다. 호출자는 여전히 선택한 글리프를 포함된 글꼴 서브셋에 표시해야 합니다.

2026-05-22 Version 2.119.43

  • OpenType GSUB 스타일러스 대체 항목 조회: 새로운 THotPDF.GetSingleSubstituteGlyph (InputGID, FeatureTag) 함수는 글꼴의 GSUB ScriptList / FeatureList / LookupList 체인을 DFLT 스크립트의 기본 LangSys 아래에서 탐색하고, 요청된 기능에 연결된 모든 LookupType 1 (단일 대체) 하위 테이블을 적용하여 대체된 글리프 ID를 반환합니다. 가장 일반적인 스타일러스 대체 기능 태그는 'salt' (스타일러스 대체), 'ss01' ~ 'ss20' (스타일러스 세트 1-20), 'aalt' (모든 대체 항목 사용), 'titl' (제목 대체 항목), 'subs' / 'sups' (아래 첨자 / 위 첨자), 'frac' (분수) 및 'ordn' (순서)입니다. 4바이트 OpenType 기능 태그 중 기능 체인에 LookupType 1 하위 테이블이 포함된 모든 태그가 지원됩니다. Coverage Format 1 (정렬된 글리프 배열, 이진 검색) 및 Format 2 (범위 레코드) 모두 지원됩니다. 단일 대체 형식 1 (델타) 및 형식 2 (대체 배열) 모두 구현되었습니다. RegisterUnicodeTTF는 이제 cmap과 함께 GSUB 테이블 오프셋/길이를 캐싱하여 쿼리 시간 GSUB 탐색 시 테이블 디렉터리를 다시 스캔하지 않도록 합니다. GSUB 테이블이 없는 글꼴, 글꼴의 DFLT 스크립트에서 광고하지 않는 4바이트 태그를 전달하는 호출자, 그리고 조회의 Coverage에 없는 GID의 경우 InputGID가 변경되지 않고 반환되므로 API를 호출해도 안전하며, 최선을 다해 대체하거나 그대로 반환합니다. 기능의 조회 체인에서 발견된 LookupType 2-8 하위 테이블은 이 첫 번째 단계에서 조용히 건너뇍니다. 다중 대체 / 대체 대체 / 리가처 대체 / 컨텍스트 체인 및 자동 모양 파이프라인 통합은 향후 버전에서 제공될 예정입니다.

2026-05-22 Version 2.119.42

  • AcroForm의 /DR 리소스는 이제 여러 개의 Unicode 폰트를 지원합니다. v2.56.0 버전에서 SetFormUnicodeFontDict는 호출자가 제공한 단일 폰트만 추적하며, 이 폰트는 AcroForm의 /DA 기본 폰트가 됩니다. 따라서 여러 스크립트가 필요한 다국어 폼(예: PDF 파일 내에서 아랍어, CJK, 라틴어)의 경우, 사용자는 /DR /Font 딕셔너리를 수동으로 작성해야 했습니다. 새로운 THotPDF.RegisterAcroFormFont(LogicalName, FontDict) 함수는 지정된 논리적 이름으로 추가 Unicode 폰트를 등록하고, 각 필드의 /DA 문자열(/ 12 Tf)에서 사용할 수 있도록 하며, v2.56.0 버전의 기본 폰트와 함께 AcroForm /DR /Font 딕셔너리에 해당 폰트를 추가합니다. 등록 순서는 유지되므로 생성되는 /DR 딕셔너리는 항상 동일합니다. SetFormUnicodeFontDict의 기본 폰트 또는 이전에 등록된 폰트와 이름이 충돌하는 경우 오류가 발생합니다. 또한 빈 LogicalName 또는 nil FontDict인 경우에도 오류가 발생합니다. SetFormUnicodeFontDict('', nil)을 사용하여 초기화하면 추가 폰트 등록 정보도 지워져서, 깨끗한 상태에서 Unicode 워크플로우를 시작할 수 있습니다. 모든 PDF/A 및 PDF/X 레벨에서 사용 가능하며, 복합 Unicode 폰트는 구조적 폼 메타데이터이며, 상호 작용 스크립트가 아닙니다.

2026-05-22 Version 2.119.41

  • PDF 1.7 §14.8.4 表 333 中定义的标准结构类型枚举:新的 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

  • 구조 요소 속성 설정기: 세 가지 새로운 도우미 기능이 v2.88.0의 /Alt 및 /ActualText, 그리고 v2.95.0의 /ID와 함께 사용되는 각 요소별 PDF 텍스트 문자열 속성을 채웁니다. 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를 설치합니다 (검증 이벤트, 사용자가 새 값을 커밋한 후 발생하며, 일반적으로 이벤트.rc := false를 통해 입력 값의 범위를 확인하거나 정규식 검증을 수행하는 데 사용됩니다). THotPDF.AttachFieldCalculateAction은 /AA /C를 설치합니다 (계산 이벤트, 카탈로그 /AcroForm /CO 계산 순서에 따라 모든 종속 필드가 변경될 때 발생하며, 일반적으로 총계를 계산하거나 세금을 계산하는 데 사용됩니다). 이 네 가지 래퍼 모두 동일한 FFormFields /T 조회를 사용하며, idempotent last-call-wins 대체 의미 체계를 가지며, PDF/A + PDF/X JavaScript 보호 기능을 제공합니다. 동일한 /AA 사전 내의 다른 트리거 키 (/E /X /D /U /Fo /Bl 주석 트리거 및 세 가지 관련 양식 필드 트리거)는 그대로 유지됩니다. 내부 리팩터링: AttachFieldKeyStrokeAction은 이제 공유 _InstallFieldTriggerJSAction 도우미에게 위임을 하며, 기존 v2.119.37 호출자는 바이트 단위로 동일한 예외 메시지를 확인합니다.

2026-05-22 Version 2.119.38

  • RegisterUnicodeTTF 现在可以从加载的字体的 cmap 格式 12 子表中捕获补充多语言平面 (SMP,U+10000-U+10FFFF) 码位到字形的映射。 在之前的版本中,SMP 条目会被静默地忽略,因为码位到字形的查找是一个 BMP 尺寸的数组。 v2.119.38 添加了一个并行稀疏列表 (FUnicodeCpToGidSMP),该列表与 BMP 数组并行填充。 新的公共方法 GetUnicodeGlyphForCodepoint(Cp) 返回任何 Unicode 码位(最多 U+10FFFF)的字形 ID,或者当码位在加载的字体的 cmap 中没有映射时,返回 0 (.notdef)。 这仅是一个功能增强:生成器端的十六进制编码管道、/CIDToGIDMap 流和 ToUnicode CMap 仍然以 BMP 为中心,因此,要将 SMP 字符写入 PDF 文本流,调用方仍然需要自行发出 UTF-16BE 代理对。 全面的、支持代理对的文本流输出将在未来的版本中实现。 仅支持格式 4 的字体将获得一个空的 SMP 列表,这符合预期。

2026-05-22 Version 2.119.37

  • 새로운 AcroForm 키 입력 트리거 도우미: `THotPDF.AttachFieldKeyStrokeAction(FieldName, JavaScriptBody)`는 지정된 이름의 폼 위젯을 해당 `/T` 값으로 찾아 `/AA`에 `/K` JavaScript 액션을 설치합니다. 이를 통해 PDF 리더가 텍스트 입력 중에 발생하는 모든 키 입력에 대해 스크립트를 실행합니다. 사용 사례에는 실시간 입력 유효성 검사(숫자/날짜/정규식), 입력 마스킹, 그리고 다른 필드의 편집으로 인해 업데이트되는 계산 필드가 포함됩니다. 이 도우미는멱등성을 가집니다. 즉, 반복적인 호출은 기존의 `/K` 항목을 대체하지만, 동일한 `/AA` 딕셔너리에 이미 존재하는 다른 트리거 키(예: `/F` 형식, `/V` 유효성 검사, `/C` 재계산, `/Bl` 블러, `/Fo` 포커스 등)는 유지합니다. PDF/A의 모든 레벨(ISO 19005-1 §6.6.1, -2/-3 §6.5.1) 및 PDF/X의 모든 레벨(ISO 15930 사전 인쇄)에서는 JavaScript 액션을 금지하므로, 해당 규정 준수 플래그가 비어 있지 않으면 도우미는 관련 사양 참조와 함께 즉시 오류를 발생시킵니다. 이는 PDF 1.7 §12.6.3 트리거 이벤트 딕셔너리와 §12.7.5.3 표 246의 폼 필드 `/K` 키를 기반으로 합니다.

2026-05-22 Version 2.119.36

  • `BeginTaggedContent` 함수는 이제 PDF 1.7 §14.8.4 표 322에 정의된 네 가지 선택적 마크 콘텐츠 시퀀스 속성(Lang / Alt / ActualText / ExpansionText)을 허용하며, 기존 MCID 항목과 함께 이를 하나의 인라인 BDC 속성 사전으로 출력합니다. `Lang`은 런에 대한 BCP-47 자연어 태그를 포함하며, 화면 판독기 및 언어 인식 텍스트 추출에 사용됩니다. `Alt`는 텍스트가 아닌 장식적인 런에 대한 대체 설명입니다. `ActualText`는 콘텐츠 추출 및 시각적 글리프 시퀀스 대신 사용되는 대체 텍스트이며, 특히 보이는 문자가 기본 의미 텍스트와 다른 리가처 및 스타일화된 글리프에 필수적입니다. `ExpansionText`는 약어를 확장하는 `/E` 키를 포함합니다. 빈 매개변수는 해당 항목을 건너뛰므로 인라인 사전에는 호출자가 명시적으로 채우는 키만 포함됩니다. 또한 기존의 두 인자 호출 방식은 v2.119.35 출력과 동일한 바이트를 유지합니다. PDF 리터럴 문자열 이스케이프(괄호 및 백슬래시)는 자동으로 처리됩니다. ASCII가 아닌 페이로드(CJK `ActualText`, Indic `Alt` 등)의 경우, 호출자는 `U+FEFF` BOM을 사용하여 바이트를 UTF-16BE로 사전 인코딩하고 결과를 `AnsiString` 인수에 넣습니다. 또한, `StructElem` 연결 없이 직접 BDC 제어가 필요한 호출자를 위한 저수준 페이지 스트림 API `BeginMarkedContentMCIDProps`도 제공됩니다.

2026-05-22 Version 2.119.35

  • 아랍 확장 문자 A의 핵심 9자 페르시아어/우르두어 부분 집합이 v2.85.0 버전의 렌더링 엔진 측 4자리 셰이퍼에 참여합니다. AutoShapeArabic 기능을 활성화하면 다음 문자는 동일한 조인 컨텍스트 알고리즘을 사용하여 기본 아랍 문자 블록에 사용되는 U+FB50-U+FBFF 아랍 표현 형태-A 글리프로 매핑됩니다. 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)는 아랍 렌더링 모델에 따라 격리/종결만 보여줍니다. 다른 아랍 확장 문자 (ALEF WASLA U+0671, NOON GHUNNA U+06BA, HEH 변형 U+06C0-U+06C3, 전체 아랍 보충 문자 U+0750-U+077F)는 그대로 통과되며, 향후 버전에 적용될 예정입니다. 페르시아어/우르두어 이외의 아랍어 텍스트는 v2.119.34 버전과 동일한 바이트로 출력됩니다.

2026-05-22 Version 2.119.34

  • PDF 이름 처리 기능은 PDF 객체를 가져오거나 복사할 때 ISO 32000-1의 #XX 이스케이프 시퀀스를 디코딩합니다. 리소스 이름, 스팟 컬러 이름, 구조 역할 이름 및 /PANTONE#20216#20CVC와 같은 다른 이름 객체는 이제 의도된 바이트 값으로 HotPDF를 통해 왕복되며, 이전에 이스케이프된 숫자 기호가 두 번 적용되어 복사되는 문제가 해결되었습니다.

2026-05-22 Version 2.119.33

  • PDF 날짜 처리 기능이 이제 ISO 32000-1 날짜 문자열 규칙을 더 엄격하게 따릅니다. 문서 정보, XMP에서 파생된 날짜 및 서명 타임스탬프는 현재 시스템 시간을 자동으로 대체하는 대신 호출자가 제공한 `TDateTime` 값을 사용하며, 파서는 로컬 날짜/시간 필드를 손상시키지 않고 표준 옵션 날짜 필드와 시간대 접미사를 허용합니다.
  • PDF 가져오기 필터 처리 기능이 이제 ASCIIHexDecode, ASCII85Decode 및 RunLengthDecode 도우미 기능을 명시적으로 제공하며, LZWDecode의 기본 EarlyChange 값은 PDF 기본값인 1과 일치하도록 변경되었습니다. 이를 통해 이전 PDF 스트림 필터를 사용하는 가져온 페이지 또는 복사된 페이지와의 호환성이 향상되었습니다.

2026-05-21 Version 2.119.32

  • 아랍어 LAM-ALEF 필수 리가처 결합이 이제 v2.85.0 버전의 렌더링 엔진에 적용되었습니다. AutoShapeArabic 기능이 활성화되면, U+0644 LAM (원시 형태 또는 네 가지 형태 중 하나: FEDD-FEE0) 다음에 ALEF의 네 가지 변형 중 하나 (MADDA U+0622, HAMZA-위 U+0623, HAMZA-아래 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

  • 새로운 DevExpress ExpressPrinting 시스템 내보내기 어댑터: `dxHotPDFExportReportLinkToFile` 및 `dxHotPDFExportReportLinkToStream`은 `TBasedxReportLink` (cxGrid, cxRichEdit, cxScheduler, cxPivotGrid 및 유사한 인쇄 가능한 구성 요소를 `TdxComponentPrinter`와 연결하는 추상 링크 계열)을 받아 각 렌더링된 페이지를 HotPDF를 통해 전달하며, DevExpress의 자체 `dxPSExportToPDF` 엔진을 사용하지 않습니다. 이 어댑터는 DevExpress의 내부 내보내기 루프를 반영합니다. 즉, 보고서를 다시 생성하고 각 페이지마다 `TMetafileCanvas`에 페이지를 그리고, 향상된 메타파일을 HotPDF로 보냅니다. 옵션 기록에는 제목, 작성자, 주제, 키워드, PDF 버전, 압축 및 렌더링 DPI가 포함됩니다. FastReport, QuickReport, ReportBuilder 어댑터와 동일한 메타파일 브리지 제한 사항이 적용됩니다. 즉, AcroForm 필드, 개요, PDF/A/PDF/X 기능은 지원되지 않습니다. 이 어댑터는 `Lib/Addons/DevExpress/` 폴더에 있으며, `HotPDF*.dpk`의 주 파일에는 포함되어 있지 않습니다.

2026-05-20 Version 2.119.30

  • 새로운 ReportBuilder 장치 클래스: `TppHotPDFDevice`는 `TppGraphicsDevice`에서 파생되었으므로, `TppReport.PrinterDevice` 또는 `TppPublisher.Device`에 할당되면 ReportBuilder의 표준 퍼블리셔 → 장치 체인에 연결됩니다. 각 페이지는 일시적인 `TMetafileCanvas`에 렌더링되고 (BeforeRenderPage에서 생성되고, AfterRenderPage에서 완료됨), `TMetafile`로 캡처되어 HotPDF의 EMF 임포터 (`HPDFEmf.ShowEnhancedMetafile`)를 통해 처리됩니다. 속성을 통해 제목, 작성자, 주제, 키워드, PDF 버전, 압축 수준, 압축 여부를 설정할 수 있습니다. `SetOutputStream` 메서드는 PDF 바이트를 호출자가 제공하는 `TStream`으로 보냅니다. 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`에 캐싱하는 페이지별 메타파일을 가져와서 HotPDF의 EMF 임포터(`HPDFEmf.ShowEnhancedMetafile`)를 통해 처리합니다. 속성을 통해 제목, 작성자, 주제, 키워드, PDF 버전, 압축 수준, 압축 여부를 설정할 수 있습니다. `SetOutputStream`은 PDF 바이트를 디스크 대신 호출자가 제공하는 `TStream`으로 보냅니다. 이 어댑터는 FastReport 어댑터와 동일한 메타파일 브리지 제한 사항을 가지고 있습니다. 즉, AcroForm 필드, 개요, PDF/A/PDF/X 기능을 지원하지 않습니다. 이 어댑터는 `Lib/Addons/QuickReport/` 폴더에 있으며, `HotPDF*.dpk`의 주요 파일에는 포함되어 있지 않습니다.

2026-05-20 Version 2.119.28

  • 새로운 FastReport 4 / FastReport VCL 내보내기 어댑터: `TfrxHotPDFExport`는 `TfrxCustomExportFilter`에서 파생되어 FastReport 코어 변경 없이 일반적인 `MyReport.Export(MyExportInstance)` 워크플로우에 통합됩니다. 이 어댑터는 준비된 각 페이지를 HotPDF의 EMF 가져오기 기능(FastReport의 `TfrxPreviewPages.DrawPage → TMetafileCanvas → HotPDF.ShowEnhancedMetafile`를 통해)을 통해 전달하므로, FastReport의 표준 레이아웃 엔진에서 렌더링된 벡터 및 래스터 페이지 콘텐츠가 개별 객체 코드를 사용하지 않고도 유지됩니다. 속성을 통해 제목, 작성자, 주제, 키워드, PDF 버전, 압축 수준 및 렌더링 DPI를 제어할 수 있습니다. 제한 사항: AcroForm 필드, 개요, PDF/A / PDF/X 기능은 지원하지 않습니다(이러한 기능은 개별 객체 코드를 사용해야 하며, 향후 버전에 계획되어 있습니다). 이 어댑터는 `Lib/Addions/FastReport4/`에 포함되어 있으며, HotPDF의 기본 `.dpk` 파일에는 포함되어 있지 않습니다. 사용자는 해당 FastReport 패키지와 함께 자신의 프로젝트에 이 어댑터를 추가해야 합니다.

2026-05-20 Version 2.119.27

  • THotPDF.SignPDFWithPFX(InputPDFPath, OutputPDFPath, PFXFilePath, Password) 함수는 PFX 기반의 PDF 서명 기능을 제공합니다. 이 함수는 서명이 될 PDF 파일을 로드하고, AddSignedSignatureField 플레이스홀더를 포함하며, PFX/PKCS#12 파일을 파싱하고, 지정된 바이트 범위에 대한 완전한 CMS SignedData(RFC 5652)를 생성하여 서명된 PDF 파일을 한 번에 작성합니다. 또한, 메모리 내 작업에 사용할 수 있는 TStream 기반의 오버로드 함수도 제공됩니다. PDF의 /Contents 영역은 CMS DER 헤더를 저장할 수 있을 만큼 충분히 커야 하며, 기본적으로 8192 바이트는 1024/2048비트 RSA 서명에 적합합니다. PBES2 + AES-256-CBC로 암호화된 PFX 파일만 지원합니다 (v2.119.26 PKCS#12 파서의 제한).
  • 새로운 HPDFCMS 모듈: CMS SignedData 빌더. HPDFCMSBuildSignedData는 ContentInfo를 SignedData와 SignerInfo로 구성하며, id-data 분리 콘텐츠, contentType, messageDigest 및 signingTime 서명 속성(RFC 5652 §5.4에 따라 DER 순서로 정렬)을 포함합니다. IssuerAndSerialNumber 서명 식별자는 X.509 인증서에서 추출되며, RSA + SHA-256 서명 알고리즘을 사용하고, X.509 인증서는 [0] 암시적 인증서로 래핑됩니다. 또한, 스트리밍된 두 창 다이제스트를 위한 HPDFCMSSHA256ByteRanges 및 /Contents 플레이스홀더 주입을 위한 HPDFCMSBytesToHex를 제공합니다. 이 기능은 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 컨테이너 파서를 제공하며, OpenSSL 3.0 이상, Windows 11 이상의 certutil, 그리고 macOS Keychain Access에서 .pfx / .p12 파일을 읽어들입니다. 또한, PBES2 (PBKDF2-HMAC-SHA-256 + AES-256-CBC) 방식으로 암호화된 SafeBag 내용을 해독하고, X.509 인증서 DER 데이터와 RSA 개인 키 파라미터를 추출합니다. 이 모듈은 CertDER, Modulus, PublicExponent, PrivateExponent 값을 포함하는 THPDFPFXKeyMaterial 레코드를 반환하며, 이를 통해 다운스트림 CMS / 서명 코드가 직접 사용할 수 있습니다. 잘못된 암호는 PKCS#7 패딩 해제 실패를 통해 감지됩니다. 이전 버전의 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)이 추가되었습니다. RFC 4231 HMAC 벡터 및 표준 PBKDF2-SHA-256 참조 출력에 대한 검증을 완료했습니다. 또한 v2.119.23 ASN.1 디코더 및 v2.119.24 RSA 기능과 함께, 최신 (OpenSSL ≥ 3.0 / Windows 11 이상) PKCS#12 / PFX 파일에서 사용되는 PBES2-AES-256 SafeBag 복호화에 필요한 암호화 기반을 완성했습니다.

2026-05-20 Version 2.119.24

  • 새로운 HPDFRSA 모듈이 추가되었습니다. 이 모듈은 다중 정밀도 정수 연산, RSA 모듈러 지수 연산, 그리고 PKCS#1 v1.5 EMSA 인코딩 기능을 제공합니다. 실제 2048/4096비트 RSA 키를 사용하여 서명할 수 있을 만큼 충분히 큰 크기를 지원합니다. v2.119.23에 추가된 ASN.1 디코더와 함께, 이 모듈은 예정된 내부 PFX 기반 PDF 서명 파이프라인에 필요한 암호화 기본 기능을 완성합니다. 아직 사용자에게 노출되는 API는 없으며, 이는 PKCS#12 + CMS 레이어가 적용될 때까지 사용할 내부 인프라입니다.

2026-05-20 Version 2.119.23

  • 새로운 HPDFASN1 모듈이 추가되었습니다. 이 모듈은 ASN.1의 일부를 디코딩하는 데 사용되며, HotPDF에서 PKCS#12 키 저장소, X.509 인증서 및 CMS/PKCS#7 서명 데이터 컨테이너를 읽는 데 필요합니다. THPDFASN1Node (파싱된 태그-길이-값 설명자), THPDFASN1ParseNode / ParseAt, Content / ToInteger / ToBigInt / ToOID / ToString 접근자, 그리고 FirstChild / NextSibling / Children 반복기를 제공합니다. 이 모듈은 무한 길이의 BER 형식과 높은 태그 번호(>= 31) 인코딩을 명시적으로 거부하며, 이는 DER의 엄격한 부분집합을 반영합니다. 이는 향후 릴리스에 포함될 내부 PFX 서명 파이프라인을 위한 인프라이며, 현재 사용자에게 노출되는 API는 없습니다.

2026-05-20 Version 2.119.22

  • THPDFPage 클래스의 AddPolylineAnnotation 및 AddPolygonAnnotation 메서드에 새로운 오버로드가 추가되었으며, 이 오버로드는 완전한 메타데이터를 지원합니다. 이 새로운 오버로드는 THPDFCurrPoint 정점 배열과 선택적인 THPDFPolyExtras 레코드를 인수로 받습니다. THPDFPolyExtras 레코드는 ISO 32000-1 §12.5.6.9에서 정의된 선택적 항목인 /IC(내부 색상), /BE(흐릿한 테두리, 솔리드 또는 흐릿한 스타일 및 강도), /IT(의도: PolyLineDimension, PolyLineFlight, PolygonCloud, PolygonDimension) 및 PolyLine에 대한 /LE(선 끝 스타일)을 노출합니다. 초기화되지 않은 레코드를 사용하려면 HPDFDefaultPolyExtras() 함수를 사용하십시오. 새로운 오버로드는 최소 두 개의 정점이 제공되었는지 확인하고, 의도에 따라 문서 버전을 자동으로 업데이트합니다(PDF 1.5 / 1.6 / 1.7). 이전의 인터리브드-싱글 오버로드는 변경 없이 계속 사용 가능합니다.

2026-05-20 Version 2.119.21

  • 새로운 라인 주석 기능: `AddLineAnnotation` 함수에 `THPDFLineExtras` 레코드를 받아 PDF 1.6/1.7 §12.5.6.7 표 175에 정의된 선택적 항목을 제어하는 세 번째 오버로드가 추가되었습니다. 여기에는 다음 항목이 포함됩니다. `/IC` (채워진 화살표, 다이아몬드 등), `/LL` (선 길이), `/LLE` (선 확장), `/LLO` (PDF 1.7), `/Cap` (캡션 플래그 및 `/CP` 위치 (/Inline 또는 /Top, PDF 1.7)) 및 `/CO` (캡션 오프셋), 그리고 `/IT` (라인 화살표/라인 치수). `HPDFDefaultLineExtras()` 함수를 사용하여 초기화된 레코드로 시작합니다. 새로운 오버로드는 요청된 경우 문서 버전을 자동으로 PDF 1.6 (또는 PDF 1.7)으로 업데이트합니다. 이전 두 오버로드는 동일한 바이트 출력을 생성하며, 호출자가 실제로 요청하는 항목만 기록됩니다.

2026-05-20 Version 2.119.20

  • THPDFButtonAction에 baShow (baHide와 반대로, 숨겨진 위젯을 다시 표시하기 위해 /H false를 발생시킴) 및 baImportData (/S /ImportData /F 파일 경로를 사용하여 클릭 시 FDF 폼 데이터를 로드함, ISO 32000-1 §12.7.5.4)라는 새로운 버튼 동작이 추가되었습니다. baShow는 PDF/A 및 PDF/X에서 허용되지만, baImportData는 ISO 19005-1 §6.6.1 및 ISO 15930 사전 인쇄 표준에 따라 둘 다에서 사용이 제한됩니다.
  • 새로운 다중 필드 숨기기/표시 기능이 추가되었습니다: `THPDFPage.AddPushButtonWithHideAction(FieldName, Caption, Targets, Hide, Rectangle, Flags)`는 대상 필드 이름 배열과 명시적인 `Hide` 부울 값을 받아들여, 하나의 버튼 클릭으로 여러 위젯의 표시 상태를 전환할 수 있습니다. 빈 `Targets` 배열은 오류를 발생시킵니다. PDF/A 및 PDF/X 모두 이 기능을 지원합니다 (위젯 표시 상태에만 적용).

2026-05-20 Version 2.119.19

  • THotPDFPage.AddPushButtonWithSubmitAction(FieldName, Caption, URL, Rectangle, SubmitFlags) 함수는 새로운 THPDFSubmitFormFlags 타입셋을 통해 ISO 32000-1 §12.7.5.2 표 237에 정의된 모든 플래그를 제공합니다. 이제 사용자는 sffExportFormatHTML, sffXFDF, sffSubmitPDF (제출 형식), sffGetMethod (HTTP GET vs POST), sffIncludeAnnotations, sffSubmitCoordinates, sffCanonicalFormat, sffIncludeNoValueFields, sffIncludeAppendSaves, sffExclNonUserAnnots, sffEmbedForm 등 다양한 플래그를 조합하여 사용할 수 있으며, 이는 기존 baSubmitURL 경로에서 하드코딩된 /Flags 0 (FDF + POST)를 대체합니다. 기존의 AddPushButtonWithAction(.., baSubmitURL, ..) 함수는 이전 버전과의 호환성을 위해 여전히 /Flags 0을 사용합니다. baSubmitURL과 마찬가지로, PDF/A에서는 허용되지만 PDF/X에서는 제한됩니다.

2026-05-20 Version 2.119.18

  • THotPDFButtonAction에 baNamed 및 baHide 기능이 추가되었습니다. baNamed는 "/S /Named /N " 액션을 발생시키며 (ISO 32000-1 §12.6.4.11), 이는 네 가지 표준 탐색 명령(NextPage, PrevPage, FirstPage, LastPage) 및 Acrobat 확장 기능(Print, SaveAs)에 적합합니다 (PDF/A는 ISO 19005-1 §6.6.1에 따라 네 가지 모두를 허용). 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). 이제 `GoTo` / `GoToR` 액션 및 개요 `/Dest` 항목은 페이지 번호를 직접 코딩하는 대신 이름으로 대상을 참조할 수 있으며, 이를 통해 페이지 삽입/삭제/재정렬 시 교차 참조의 안정성을 유지합니다. 새로운 `THPDFDestinationFitMode` 열거형은 사양에 정의된 모든 8가지 적합 모드(XYZ, Fit, FitH, FitV, FitR, FitB, FitBH, FitBV)를 포함합니다. 이 메서드는 빈 `Name`, 범위를 벗어난 `PageIndex`, 중복 `Name`이 있는 경우 예외를 발생시키며, 필요한 경우 문서 버전을 PDF 1.2로 자동으로 업데이트합니다. PDF/A 또는 PDF/X 제한은 없으며, 탐색 도구는 모든 프로필에서 사양에 따라 허용됩니다.

2026-05-20 Version 2.119.16

  • THPDFPage.AddLineAnnotation 함수는 이제 시작/종료 선 스타일을 지정할 수 있는 기능을 추가했습니다. 새로운 THPDFLineEndingStyle 열거형을 통해 ISO 32000-1 §12.5.6.7 표 176에 정의된 모든 스타일(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 Table 153 /C 및 /F). 이제 개요 패널에서 북마크를 색상으로 표시하거나 굵게 또는 기울임꼴로 강조하여 챕터를 그룹화하고, 완료되지 않았거나 주의가 필요한 섹션을 표시하거나, 브랜드 스타일과 일치시킬 수 있습니다. 색상은 기본적으로 clNone(색상 정보가 없는 이전 출력과 동일)이며, 굵게 및 기울임꼴은 기본적으로 false입니다. AddChild를 호출한 후 속성을 설정하면 실시간 개요 사전을 즉시 업데이트합니다. Color를 clNone으로 설정하거나 굵게 및 기울임꼴을 모두 false로 설정하면 /C 및 /F 항목이 제거됩니다.

2026-05-20 Version 2.119.14

  • THotPDF은 이제 `RegisterDocumentJavaScript(Name, Body)`를 통해 문서 수준의 명명된 JavaScript 레지스트리를 제공합니다. 각 등록 항목은 간접 /S /JavaScript /JS 딕셔너리로 Catalog /Names /JavaScript 이름 트리에 직렬화됩니다 (ISO 32000-1 §7.7.4.4 + §12.6.4.16). AcroForm 위젯 작업 및 문서 열기 작업은 뷰어의 JavaScript 엔진(Acrobat, Foxit)을 통해 등록된 함수를 이름으로 호출할 수 있습니다. 이는 여러 위젯에서 검증, 서식 지정 또는 계산 도우미 라이브러리를 공유하는 데 유용하며, 각 /A 작업 딕셔너리에 JS 소스 코드를 중복할 필요가 없습니다. 이 메서드는 모든 PDFACompliance 수준 (ISO 19005-1 §6.6.1) 및 모든 PDFXCompliance 수준 (ISO 15930 사전 인쇄 워크플로우)에서 오류를 발생시키며, 빈 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` 액션 유형이 어떤 PDFA 규정 준수 수준(PDF/A-1/2/3)에서도 사용될 때 예외를 발생시킵니다. ISO 19005-1 §6.6.1 / ISO 19005-2 §6.5.1 / ISO 19005-3 §6.5.1은 모든 PDF/A 수준에서 JavaScript, ResetForm 및 ImportData 액션을 금지합니다. `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` 함수는 이제 `PDFACompliance`가 모든 수준(PDF/A-1/2/3)에서 활성화되면 예외를 발생시킵니다. ISO 19005-1 §6.5.2 / ISO 19005-2 §6.6.1 / ISO 19005-3 §6.6.1은 모든 PDF/A 수준에서 Screen, 3D 및 RichMedia(멀티미디어 / Adobe 확장 레벨 3) 주석 유형을 금지합니다. 동일한 제한 사항이 `PDFXCompliance`에서도 적용되며, ISO 15930 사전 인쇄 워크플로우에서는 멀티미디어 유형을 거부합니다.
  • PDF/A-1 준수 오류 수정: `AddWatermarkAnnotation` 및 `AddRedactAnnotation` 함수는 이제 `PDFACompliance`가 PDF/A-1로 설정된 경우 예외를 발생시킵니다. 워터마크(PDF 1.6) 및 검열(PDF 1.7)은 PDF/A-1의 PDF 1.4 기반(ISO 19005-1 §6.5.2)과 호환되지 않는 후기 PDF 1.4 주석 유형입니다. 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에서는 모든 투명 효과를 금지합니다. 페이지 수준의 투명 그룹(페이지 `/Group /S /Transparency` 딕셔너리)은 페이지 전체에 대한 투명 합성 모델을 활성화하며, 이는 §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에 따르면 ExtGState /HT의 경우 "/Default" 이름만 허용되며, 사용자 정의 하프톤 사전(Type 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에서는 PDF/A-1에서 문서 Names 딕셔너리의 /EmbeddedFiles 키를 명시적으로 금지합니다. PDF/A-3의 경우, 필요한 Catalog /AF 배열 및 /AFRelationship 키를 포함하기 위해 `AddPDFA3AssociatedFile()` 함수를 통해 문서 첨부 파일을 등록해야 합니다 (ISO 19005-3:2012 부록 E 참조). PDF/A-2는 첨부된 파일이 PDF/A 규격에 부합하는 경우 문서 첨부 파일을 계속 허용합니다.

2026-05-20 Version 2.119.6

  • PDF/A 규정 준수 오류 수정: PDF 표준 글꼴(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로 설정하거나 PDF/A 출력을 위해 실제 글꼴 파일로 RegisterUnicodeTTF()를 사용해야 합니다.
  • 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 키를 사용할 수 없도록 규정합니다. 이제 어떤 PDFACompliance 값으로든 SetActionScript를 호출하면 자세한 예외가 발생합니다. 추가적인 안전 장치로, EndDoc에서 OpenAction JavaScript 및 카탈로그 /AA 출력을 처리하는 부분도 PDFACompliance가 활성화되면 자동으로 건너뛰도록 설정되어, 내부 경로를 통해라도 규정을 준수하지 않는 키가 기록되지 않도록 합니다.

2026-05-20 Version 2.119.4

  • PDF/A 규정 준수 오류 수정: `PDFACompliance`가 활성화되면 `AcroForm /NeedAppearances`가 이제 `AutoFormAppearances` 설정에 관계없이 항상 `false`로 설정됩니다. 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 서브셋은 이제 PDFACompliance가 활성화된 경우 해당 FontDescriptor에 /CIDSet 스트림을 포함합니다. ISO 19005-1:2005 §6.3.5 및 ISO 19005-2:2011 / ISO 19005-3:2012 §6.2.11에 따르면 CIDFont 서브셋은 임베디드 글꼴 프로그램에 포함된 CID 값이 무엇인지 나타내는 /CIDSet 비트스트림을 포함해야 합니다. HotPDF는 CID가 Unicode 코드포인트와 동일한 Identity-H 인코딩을 사용하므로, CIDSet은 문서에 사용된 코드포인트 집합에서 직접 생성됩니다. 이 비트스트림은 FlateDecode로 압축되고 기존 FontDescriptor에 간접 스트림 객체로 연결됩니다. 이를 통해 이전에 감지되지 않았던 모든 PDF/A 레벨의 문제를 해결합니다 (이전 규정 준수 검사에서는 이 기능이 이미 구현되어 있다고 잘못 보고했습니다).

2026-05-20 Version 2.119.2

  • PDF/A-2 및 PDF/A-3 규격 준수 문제를 해결했습니다. 이제 링크가 아니거나 팝업이 아닌 주석 유형(텍스트 메모, 자유 텍스트, 선, 사각형, 원, 도장, 파일 첨부)의 경우, `PDFACompliance`가 PDF/A-2 또는 PDF/A-3 레벨로 설정되면 주석 모양 사전(/AP /N)이 자동으로 생성됩니다. 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 링크)의 경우, PDFACompliance가 활성화되면 이제 자동으로 /F 인쇄 플래그(비트 3 = 1, 값 4)가 설정됩니다. 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 키를 사용할 수 없다고 명시합니다. PDF/A-1에서 RegisterOptionalContentGroup을 호출하면 이제 선택적 콘텐츠가 필요한 경우 PDF/A-2 이상을 사용하도록 안내하는 자세한 예외가 발생합니다. 또한 EndDoc에서 /OCProperties를 출력하는 기능도 비활성화되어 OCG가 등록된 경우에도 숨겨진 방식으로 규격을 준수하지 못하는 상황을 방지합니다.

2026-05-20 Version 2.119.0

  • ETSI EN 319 142-2 V1.2.0 §6.2에 따른 XAdES-in-PDF 컨테이너 지원 (B/C/D 시리즈의 3/3 종료). 호출자가 제공한 XAdES 서명 XML 바이트를 PDF 임베디드 파일로 포함시키고, Filespec을 Catalog /AF 배열에 등록하며, 호출자가 지정한 PDF 2.0 열거형에 따라 /AFRelationship을 설정합니다. 이는 프로듀서 측의 래퍼 기능만 제공하며, 실제 XAdES 서명 생성 (XML-DSig + ETSI EN 319 132-1 QualifyingProperties + RFC 3161 타임스탬프가 포함된 xades:UnsignedSignatureProperties)은 호출자가 사용하는 XML 암호화 라이브러리의 책임입니다 (예: Apache Santuario, .NET SignedXml, libxmlsec, XAdES 확장이 적용된 Saxon 등).
  • 새로운 메서드 `THotPDF.AddXAdESAssociatedFile(FileName, XMLBytes, Description, MimeType, Relationship)`가 추가되었습니다. 기본값은 다음과 같습니다. `MimeType`은 `'application/xml'` (ASiC-E 아카이브의 경우 일반적으로 `'application/vnd.etsi.asic-e+zip'` 사용), `Relationship`은 `'Source'` (XAdES 서명 XML은 문서의 주요 콘텐츠임). 이 메서드는 추가 메타데이터를 첨부하거나 사용자 정의 카탈로그 항목에서 교차 참조를 수행할 수 있도록 간접 파일 사양 딕셔너리를 반환합니다.
  • PDF/A 독립: v2.108 버전의 `AddPDFA3AssociatedFile` 기능과 달리 (이 기능은 PDFACompliance='3*'을 요구함), 이 도우미 기능은 PDF/A 관련 제약이 없습니다. XAdES-in-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`과 같은 이름은 엄격한 PDF 리더에 의해 두 개의 별도 이름 토큰(`/application` 다음에 `/xml`)으로 해석되어, 임베디드 파일의 `/Subtype` 인식에 문제가 발생했습니다. v2.119 버전에서는 사양에 따라 모든 10개의 구분자를 변환합니다. 구분자가 아닌 이름(HotPDF에서 생성되는 대부분의 경우)은 이전과 동일한 바이트 값을 유지합니다. PDF/A-3 부록 E (v2.108)의 MIME 유형이 이제 올바르게 생성됩니다 (`/application#2Fxml` 대신 이전의 잘못된 `/application/xml`).
  • PAdES B/C/D 시리즈가 3개의 커밋으로 마무리되었습니다. v2.117 (파트 2 §5에 따른 E-BES / E-EPES / E-LTV 확장 프로필) + 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은 이제 기본 프로필, 확장 프로필, 문서 타임스탬프, DSS 검증 정보, ESIC 확장, 시드 값을 통한 서명 제약, 그리고 XAdES-in-PDF 컨테이너를 포함한 전체 PAdES 프로듀서 범위를 지원합니다.
  • Win32 및 Win64에서 깨끗한 컴파일이 완료되었습니다. v2.108부터 v2.118까지의 기본 버전은 모두 다시 컴파일되었으며 변경 사항은 없습니다. 새로운 테스트 항목인 smoke_pades_xades는 2개의 성공적인 테스트 경로(XAdES 서명 XML을 `/AFRelationship` 및 `/Source`로 사용하고, ASiC-E 아카이브를 `/Data`로 사용)와 4개의 실패 테스트 경로(FileName이 비어 있음, XMLBytes가 비어 있음, MimeType이 비어 있음, Relationship이 유효하지 않음)를 포함합니다. Python 검증기는 `/Subtype /application#2Fxml` 및 `/Subtype /application#2Fvnd.etsi.asic-e+zip` 형식 모두를 포함하여 모든 파일 사양을 전체적으로 검증합니다. v2.108의 PDF/A-3, PAdES 및 PDF/X 테스트는 모두 다시 실행되었으며, 깨끗한 결과가 나왔습니다.

2026-05-20 Version 2.118.0

2026-05-20 Version 2.117.0

  • ETSI EN 319 142-2 V1.2.0 §5에 따른 PAdES 확장 프로필 (B/C/D 시리즈의 3단계 중 1단계). Part 1에서는 기본 CMS 속성 조합을 정의하며 (V1.2.1 §6 B-B / B-T / B-LT / B-LTA), Part 2 §5에서는 "확장" 프로필 (E-BES / E-EPES / E-LTV)이라는 별도의 패밀리를 정의합니다. 이러한 확장 프로필은 기본 설정보다 더 높은 수준의 CMS 속성 선택 기능을 제공하며, 이는 다중 정책을 사용하는 기업 환경이나 PAdES 래퍼 내에서 사용자 정의 CAdES 프로필을 사용하는 경우와 같이 유연성이 필요한 경우에 유용합니다.
  • `AddPAdESSignatureField` 프로필 매개변수는 이제 네 가지 기본 이름 외에 세 가지 추가 값을 허용합니다.
    • `'E-BES'` — 서명 인증서의 ESS 속성을 통해 기본 + 명확한 서명 인증서 바인딩 (PAdES 래퍼 내의 CAdES-BES에 해당). 기본적으로 16KB의 /Contents 예산을 사용합니다.
    • `'E-EPES'` — E-BES + 명시적인 서명 정책 식별자 서명 속성. 기본적으로 16KB의 예산을 사용하며, 호출자는 일반적으로 정책 OID 및 자격 증명 바이트를 포함하기 위해 18-20KB를 전달합니다.
    • `'E-LTV'` — CMS 속성 기반 유연한 인증 체인 + 해지 정보를 포함하는 장기 유효성 검사. 자동으로 20KB의 최소 크기로 조정됩니다 (B-LT와 동일).
  • 기본 프로필과 확장 프로필 모두에서 Producer 측의 내부 형식은 동일합니다. 모두 SubFilter `ETSI.CAdES.detached`를 사용하고, 동일한 `/ByteRange` + `/Contents` 패턴을 사용하며, 동일한 DSS + ESIC 구조를 사용합니다 (v2.110 / v2.116). 레벨의 차이는 호출자의 암호화 라이브러리가 생성하는 CMS 서명 속성 구성에만 있습니다. Profile 문자열은 검증 진단 및 기본 `/Contents` 값만 다릅니다. HotPDF는 PDF 딕셔너리 자체에 CAdES-BES, CAdES-EPES 또는 CAdES-T를 인코딩하지 않습니다.
  • PAdES 관련 도움말 주석을 업데이트하여, Part 2 V1.2.0 §4.2에서 명시하는 호출자 책임 사항을 명확히 했습니다. 변경 사항은 다음과 같습니다. SHA-256+ 해시 선택 (SHA-1 단계적 폐지), 각 Sig 필드당 하나의 SignerInfo만 허용, RFC 5755 속성 인증서 미지원, 그리고 전자 서명 정책 식별자 서명 속성을 포함해야 하는 E-EPES 요구 사항입니다. 호출자 관련 사항은 여전히 제작자의 책임 범위를 벗어나지만, API 인터페이스를 통해 이러한 사항이 명시적으로 정의되었습니다.
  • Win32 및 Win64에서 깨끗한 컴파일이 완료되었습니다. v2.108부터 v2.116까지의 기본 버전은 모두 다시 컴파일되었으며 변경 사항은 없습니다. `smoke_pades_signature`가 3개의 새로운 필드(SigEBES, SigEEPES, SigELTV)로 확장되었으며, 각 새로운 프로필 값을 자동 크기 조정, 명시적 예산 및 기본 예산 경로를 통해 테스트했습니다. Python 검증기는 모든 7개의 필드를 순회하며, 카탈로그 ESIC 확장에 대한 검증을 수행합니다 (v2.116에서 이 기능이 유지됨).
  • B/C/D 시리즈의 2단계: v2.118 버전에서는 시드 값(Seed Values)을 추가했습니다 (PDF 1.7 §12.7.5.5 + ETSI EN 319 142-1 V1.2.1 §5.5 + Part 2 V1.2.0 §4.2.6). 이를 통해 PAdES 서명 필드가 서명 과정에서 소비 장치가 준수해야 하는 핸들러/SubFilter/digest-method 제약을 선언할 수 있습니다. 3단계: v2.119 버전에서는 XAdES-in-PDF 컨테이너 지원을 추가했습니다 (Part 2 V1.2.0 §6에 따름. XAdES 서명 XML을 EmbeddedFile로 포함하고 Catalog /AF 연결).

2026-05-20 Version 2.116.0

  • 최신 ETSI 표준 버전 및 eIDAS 시행 결정에 따라 PAdES를 업데이트했습니다. 업데이트 내용은 다음과 같습니다. ETSI EN 319 142-1 V1.2.1 (2024-01, 게시됨) + ETSI EN 319 142-2 V1.2.0 (2025-03, 초안, 추가 프로필 + 확장 프로필 패밀리 + PDF 내 XAdES) + ETSI TS 119 142-3 V1.1.1 (2016-12, PAdES-DTS 문서 타임스탬프) + 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 도우미가 호출될 때마다 다음 내용을 Catalog에 안전하게 기록합니다: `<< /Extensions << /ESIC << /BaseVersion /1.7 /ExtensionLevel 1 >> >> >>`. 검증기(Adobe Acrobat 사전 검사, EU DSS, callas pdfaPilot)는 이 항목을 사용하여 문서를 PAdES 컨테이너로 식별하며, PDF 1.7 + ESIC 레벨 1 확장을 사용하고 있음을 나타냅니다.
  • `EnsurePAdESDSS` 경로의 중요한 버그 수정 사항입니다. v2.116 이전 버전에서는, 헬퍼 함수가 `Catalog.GetIndexedItem(FindValue('DSS'))`를 통해 매 호출마다 DSS 딕셔너리를 다시 확인했습니다. 이 함수는 딕셔너리 대신 카탈로그에 저장된 간접 링크 `THPDFLink`를 반환했습니다. `THPDFDictionaryObject`로의 형변환은 포인터를 조용히 잘못 해석하여, 이후의 `AddPAdESDSSCertificate` / `AddPAdESDSSOCSP` / `AddPAdESDSSCRL` / `AddPAdESDSSVRI` 호출에서 배열에 요소를 추가하는 작업을 무시하게 만들었습니다 (배열 참조가 nil로 확인되었고, `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 단계 중단 (호출자는 CMS의 경우 SHA-256+를 사용해야 함), PDF 서명당 단일 SignerInfo (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 영역의 `/Rect` (`[0 H 0 H]`에서 H는 페이지 높이)을 허용합니다. 감사 문서 및 기술 참고 사항이 EN 319 142-1 V1.2.1 / Part 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/X 규격 준수를 위해 지원하지 않는 주석 유형(PDFXCompliance ∈ {X-1a, X-3, X-4}인 경우):
    • FileAttachment — 인쇄 과정에서 포함된 파일은 사용되지 않습니다.
    • Sound — 멀티미디어 콘텐츠는 인쇄 워크플로우에 적합하지 않습니다.
    • Movie — 위와 동일한 이유입니다.
    각 진입점(AddFileAttachmentAnnotation, AddSoundAnnotation, AddMovieAnnotation)은 이제 PDF/X 프로파일에서 호출될 때, 해당 규격 섹션 진단 정보와 PDFXCompliance 값을 함께 반환합니다.
  • 금지된 작업 유형 (PDF/X 규정 준수 하에서 거부됨): Launch, JavaScript, SubmitForm, ImportData, Movie, Sound, ResetForm. 인쇄 사전 처리 워크플로우는 외부 프로그램을 실행해서는 안 되며, PDF 파일은 프린터/RIP에서만 사용되어야 하며 실행되어서는 안 됩니다. AddLaunchLink는 이제 모든 PDF/X 프로파일에서 오류를 발생시킵니다 (다른 작업들은 HotPDF에서 공개 API로 제공하지 않으므로 자동으로 처리됩니다).
  • PDF/X 시리즈가 이제 기능적으로 완성되었습니다. v2.112 (옵트인 + XMP 식별자 + 트랩 / 이름) + v2.113 (출력 의도 + ICC GTS_PDFX) + v2.114 (투명성 제한 + 페이지 박스 강제 적용) + v2.115 (금지된 주석/액션). X-1a:2001, X-3:2002, X-4:2010을 포함한 모든 세 가지 산업 표준 프로필이 지원됩니다. 호출자는 여전히 페이지 수준의 사전 인쇄 콘텐츠를 작성합니다 (정확한 CMYK 값, v2.84 TTF 서브세터를 사용한 글꼴 포함, 디자인과 일치하는 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: 투명도 제한 기능 및 ISO 15930-1:2001 / ISO 15930-3:2002 / ISO 15930-7:2010 / ISO 32000-1 §14.11.2에 따른 PageBox 적용. 이 기능은 각 페이지에 적용되는 두 가지 독립적인 제한 사항을 포함하며, 제한 방식은 v2.103 PDF/A-1의 투명도 및 페이지 관련 기능과 유사합니다.
  • 투명성 검사(§7.5): RegisterExtGState는 PDFXCompliance가 'X-1a' 또는 'X-3'일 때, 채우기 알파 값이 1보다 작거나 (/ca), 스트로크 알파 값이 1보다 작거나 (/CA), 또는 블렌드 모드가 {Normal, Compatible} 범위를 벗어나는 경우를 거부합니다. 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로 업그레이드하도록 제안합니다.
  • 페이지 박스 강제 적용(§14.11.2): 새로운 메서드 `EnsurePDFXPageBoxes`는 모든 페이지를 순회하며, `/TrimBox` 또는 `/ArtBox` 중 최소 하나가 반드시 존재하도록 합니다. `MediaBox`만으로는 충분하지 않습니다. 왜냐하면 `MediaBox`는 디자인 캔버스를 나타내지만, 인쇄소에서 필요한 최종 페이지 크기를 나타내지 않기 때문입니다. 누락된 페이지 박스가 있는 경우, 1부터 시작하는 페이지 인덱스, 관련 규격 섹션, 그리고 권장되는 `SetTrimBox` 호출 정보를 함께 오류로 표시합니다. `EndDoc`의 PDFXCompliance 단계에서 `EnsurePDFXPageBoxes`는 `OutputIntent` 검사 후에 자동으로 호출됩니다.
  • 일반적인 호출 패턴은 다음과 같습니다. PDFXCompliance, Trapped 및 AddPDFXOutputIntent를 설정한 후, 문서의 각 페이지에서 `CurrentPage.SetTrimBox(Left, Bottom, Right, Top)`을 사용하여 최종 제품의 크기에 맞게 설정해야 합니다 (예: US Letter의 경우 0 0 612 792, A4의 경우 0 0 595 842). BleedBox 사용은 권장되지만 필수 사항은 아닙니다.
  • Win32 및 Win64에서 깨끗한 컴파일이 완료되었으며, v2.108부터 v2.113까지의 기본 버전은 모두 다시 컴파일되었지만 변경 사항은 없습니다. smoke_pdfx_optin 기능은 다음과 같이 확장되었습니다. 각 프로필에서 SetTrimBox 호출이 정상적으로 수행되는지 확인하고, TrimBox가 누락된 경우 거부하는 기능을 추가했습니다. 또한, X-1a 투명도 거부 기능(ca=0.5인 경우 RegisterExtGState 호출)과 X-4 투명도가 허용되는 경우의 정상적인 동작(동일한 호출이 성공하고 ExtGState가 등록됨)을 구현했습니다. Python 검증기는 모든 "/Type /Page" 딕셔너리를 순회하며, 각 페이지에 대해 "/TrimBox" 또는 "/ArtBox" 중 적어도 하나가 존재하는지 확인합니다.
  • PDF/X 관련 기능 업데이트: v2.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: 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에 따라 OutputIntent 및 ICC 프로필 적용을 시행합니다. 모든 PDF/X 프로필은 대상 인쇄 조건을 명시하는 `/Type /OutputIntent /S /GTS_PDFX` 항목과 `/DestOutputProfile` ICC 프로필 스트림을 반드시 포함해야 합니다. 인쇄소에서는 이 정보를 사용하여 PDF 파일을 해당 인쇄 장비/종이/잉크 조합에 맞게 색상 보정을 수행합니다.
  • 새로운 `AddPDFXOutputIntent(OutputConditionIdentifier, Info, ICCProfileStream, NumComponents, AlternateCS)` 함수는 v2.102 PDF/A 래퍼와 유사하지만, GTS_PDFA1 대신 GTS_PDFX 서브타입을 생성합니다. `ICCProfileStream`이 null이 아니고 `OutputConditionIdentifier`가 비어 있지 않은지 확인하며, 프로필을 임베드하기 위해 `RegisterICCProfile`을 호출하고 (NumComponents와 일치하는 /Alternate 대체 색 공간을 자동으로 처리), `OutputIntent` 딕셔너리를 생성하기 위해 `AddOutputIntent`를 호출합니다.
  • PDFX 규정 준수 설정 시, `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(Binary Map)에서도 Normal이 아닌 경우 거부됨; X-4 표준에서는 투명도를 허용). 또한, §14.11.2에 따라 모든 페이지에 TrimBox 또는 ArtBox가 필요하도록 PageBox 적용 기능이 추가되었습니다. v2.115 버전에서는 Movie, Sound, FileAttachment, Screen, JavaScript, Launch, SubmitForm, ImportData, XFA 등과 같이 인쇄 워크플로우에 적합하지 않은 기능에 대한 제한 기능이 추가되어 관련 시리즈가 종료됩니다.

2026-05-19 Version 2.112.0

  • PDF/X (ISO 15930) 인쇄 사전 준비 기능 개발 시작. PDF/X는 상업용 인쇄업체에 인쇄 가능한 PDF 파일을 전송하기 위한 ISO 표준이며, X-1a (엄격한 CMYK + 스팟 색상), X-3 (ICC 색상 관리), X-4 (PDF 1.6 투명도 + ICCN) 프로필이 널리 사용됩니다. v2.112는 1/4 단계로, 선택적 기능 추가 및 메타데이터 설정이 포함됩니다. 전체 감사 결과 및 4단계 로드맵은 .superpowers/specs/2026-05-19-pdfx-compliance-audit.md 파일에 보관되어 있습니다.
  • THotPDF 클래스의 새로운 `PDFXCompliance: AnsiString` 속성은 `''` (비활성화, 기본값), `'X-1a'` (ISO 15930-1:2001), `'X-3'` (ISO 15930-3:2002) 또는 `'X-4'` (ISO 15930-7:2010) 값을 허용합니다. 비어 있지 않은 값을 설정하면 HotPDF가 해당 프로필에 대해 구조적으로 충족할 수 있는 모든 생산자 측 요구 사항이 자동으로 활성화됩니다.
  • 새로운 `Trapped: AnsiString` 속성(PDFXCompliance에서 필수)은 `'True'`, `'False'`, `'Unknown'` 값을 허용합니다. PDF/X 제품군은 이 DocInfo 항목을 필수로 지정하며, 이는 인쇄소가 PDF 파일이 이미 트래핑 처리되었는지 또는 사전 인쇄 단계에서 트래핑 처리가 필요한지 여부를 알 수 있도록 하기 위함입니다. 이 값은 ISO 32000-1 §14.11.6.1에 따라 PDF /Name (문자열이 아닌) 형태로 출력됩니다. 예를 들어 `<< /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" 값을 거부하며, 제목을 필수적으로 요구합니다. 또한, PDF 버전을 프로필의 필수 최소 버전으로 자동 업데이트합니다 (X-1a/X-3의 경우 PDF 1.3, X-4의 경우 PDF 1.6). 암호화와 PDFXCompliance는 충돌하는 기능이며, EnableEncrypt를 호출하거나 `ActivateProtection := True`로 설정하면, 암호 처리 없이 모든 객체를 검사해야 하는 PDF/X 워크플로우의 이유를 명확하게 설명하는 오류가 발생합니다.
  • 호출자는 여전히 출력 의도, ICC 프로필, 트림 박스/아트 박스, 유효한 사전 인쇄 색 공간, 올바른 글꼴 임베딩을 작성하며 (X-1a/X-3의 경우 투명성을 피합니다) 완전한 PDF/X 준수를 보장합니다. v2.113부터 v2.115까지의 업데이트는 이러한 격차를 해소합니다. v2.113에서는 `AddPDFXOutputIntent` (필수적인 /GTS_PDFX 의도)를 추가하고, v2.114에서는 투명성 제한 및 페이지 박스 강제 기능을 추가했으며, v2.115에서는 금지된 액션/주석/XFA 기능을 추가하여 일련의 업데이트를 완료합니다.
  • Win32 및 Win64에서 깨끗한 컴파일을 수행했습니다. v2.108, v2.109, v2.110 및 v2.111 버전을 기준으로 모든 코드를 다시 컴파일했지만 변경 사항은 없습니다. 새로운 smoke 테스트(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 (독립적인 ETSI.RFC3161 타임스탬프만 포함된 PDF)는 사실상 구현되었으며, v2.111의 `AddDocumentTimestampSignature`는 내부 서명이 없는 새 문서에서도 작동합니다. 따라서 PAdES 시리즈는 3개의 커밋으로 완료되었으며, v2.112는 PDF/X로 재분류됩니다. ETSI EN 319 142-1의 기본 프로필은 모두 지원됩니다.

2026-05-19 Version 2.111.0

2026-05-19 Version 2.110.0

2026-05-19 Version 2.109.0

  • PAdES (ETSI EN 319 142) 디지털 서명 생성 작업을 시작했습니다. v2.109은 기존 ISO 32000-1 §12.8 서명 인프라(AddSignedSignatureField 도우미의 v2)를 기반으로 하는 고수준 래퍼를 추가하며, PAdES에서 요구하는 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 신뢰 타임스탬프 포함, EU 법적 사용의 최소 요구 사항), 'B-LT' (장기 검증을 위한 DSS 검증 정보 포함), 또는 'B-LTA' (아카이빙을 위한 문서 타임스탬프 서명 포함)를 사용합니다. 이 모든 기능은 SubFilter 'ETSI.CAdES.detached'를 사용하며, profile 매개변수는 진단 정보와 기본 /Contents 바이트 할당량을 변경합니다. 다른 profile 문자열은 ETSI 열거에 정의된 값으로 처리됩니다.
  • 자동으로 크기가 조정되는 콘텐츠 예산: PAdES-B-B 및 B-T의 기본값은 16KB입니다(호출자는 더 작은 값을 제공할 수 있지만, v2.108에서 상속된 64바이트의 최소 크기를 적용합니다). PAdES-B-LT는 최소 20KB로 자동 크기 조정됩니다(CAdES + 인증 체인 + OCSP/CRL 데이터). 호출자가 제공하는 더 큰 값은 그대로 통과되며, 이 도구는 최소 크기만 조정합니다.
  • 프로듀서 범위: 이 래퍼는 `/Type /Sig` 플레이스홀더 딕셔너리를 `/SubFilter /ETSI.CAdES.detached`, `/Reason`, `/Location`, `/ContactName`, `/M (서명 날짜)`과 함께 생성합니다. 또한 `/ByteRange + /Contents` 센티넬을 추가하여 `PreparePDFForSigning` 및 `InsertSignatureHex`를 통해 서명 후 패치를 가능하게 합니다. 실제 CMS/CAdES 바이트, RFC 3161 타임스탬프 검색, OCSP/CRL 수집 및 DSS 딕셔너리 구성은 호출자의 책임입니다. 이러한 작업에는 PDF 프로듀서의 범위 밖에 있는 외부 암호화 라이브러리(OpenSSL, Bouncy Castle, Windows CAPI 등)가 필요합니다.
  • Win32 및 Win64에서 깨끗한 컴파일이 완료되었습니다. 새로운 smoke 테스트인 `smoke_pades_signature`는 네 개의 PAdES 서명 필드(B-B / B-T / B-LT / B-LTA)를 생성하고, 잘못된 프로필 값이 발생하는지 확인합니다. Python 검증기는 AcroForm의 `/SigFlags`가 3인지 확인하고, 각 위젯이 `/FT /Sig`와 `/V`를 통해 `/Type /Sig` 딕셔너리를 참조하며, 이 딕셔너리는 `/SubFilter /ETSI.CAdES.detached`를 가지고 있고, `/Contents` 플레이스홀더의 16진수 길이가 예상되는 (자동으로 조정된) 바이트 크기와 일치하는지 확인합니다.
  • 로드맵에 남아 있는 PAdES 관련 기능은 다음과 같습니다. v2.110 버전에서는 PAdES-B-LT 유효성 검사 정보(인증 체인 + OCSP/CRL)를 위한 Catalog /DSS (Document Security Store) 딕셔너리 빌더를 추가했습니다. v2.111 버전에서는 PAdES-B-LTA 아카이빙을 위한 독립 실행형 문서 타임스탬프 서명 필드를 추가했습니다. v2.112 버전(선택 사항)에서는 ETSI.RFC3161 타임스탬프만 포함하는 PDF 파일을 추가합니다.

2026-05-19 Version 2.108.0

2026-05-19 Version 2.107.0

  • PDF/A-2 및 PDF/A-3 프로듀서 시리즈의 3/4 버전에서, ISO 19005-2 §6.1.13 및 ISO 19005-3 §6.1.13의 구현 제한 사항을 적용합니다. PDF/A-1 §6.1.13은 훨씬 더 관대합니다 (문자열 길이 제한이 없음), 따라서 새로운 제한은 PDFACompliance가 PDF/A-2 이상 ( '2*' 또는 '3*' )인 경우에만 적용됩니다.
  • 새로운 공개 메서드 `EnsurePDFAImplementationLimits`는 문서의 호출자가 제어하는 값들이 규격에서 정한 제한 내에 있는지 확인합니다. `Doc.Title`, `Author`, `Subject`, `Keywords`, `Lang` 문자열은 모두 32767바이트 이하여야 하며, 각 페이지의 `MediaBox` 크기는 [3..14400] 범위 내에 있어야 합니다. `EndDoc` 함수는 `PDFACompliance`가 PDF/A-2/3으로 설정된 경우 자동으로 검증기를 호출하며, 사용자는 빌드 과정 중간에 직접 검증기를 호출하여 초기 진단을 수행할 수도 있습니다.
  • 감사 보고서에 명시된 제한 사항은 다음과 같습니다. 정수 범위는 -2³¹에서 2³¹-1까지, 실수 범위는 ±3.403×10³⁸까지, 0에 가까운 값은 ≥1.175×10⁻³⁸까지, 이름 길이는 127바이트 이하, 간접 객체 수는 8388607 이하, q/Q 중첩은 28 이하, DeviceN 색상 수는 32 이하, CID는 65535 이하입니다. HotPDF의 출력 경로는 이러한 제한을 초과하지 않습니다. 왜냐하면 이러한 제한은 HotPDF가 제어하는 생산 측 데이터 구조에 연결되어 있기 때문입니다. 검증기는 호출자가 제공하는 문자열과 페이지 경계에 중점을 둡니다. 왜냐하면 이러한 부분만이 실제 사용자가 제한을 초과할 수 있는 부분이기 때문입니다.
  • XFA 양식(§6.4.2): HotPDF은 AcroForm /XFA 또는 Catalog /NeedsRendering을 생성하지 않습니다. 이러한 요소는 PDF/A-1/2/3 표준에서 자동으로 충족되므로, 향후 다른 프로그램에서 이러한 요소가 다시 포함되지 않도록 감사 보고서에 명시되어 있습니다.
  • .notdef 글리프(PDF/A-2의 §6.2.11.8): 사양에서는 텍스트 표시 연산자가 .notdef를 참조하는 것을 금지합니다. HotPDF의 글꼴 처리 기능은 호출자가 등록된 Unicode TTF 글꼴을 사용하는 경우 이를 방지합니다(v2.74-v2.86 버전). 호출자는 원시 텍스트 출력 경로에 대한 책임을 지며, 이는 감사 보고서에 자세히 설명되어 있습니다.
  • XMP 네임스페이스(§6.6.2): 이 사양에서는 XMP 패킷 헤더에 바이트/인코딩 속성을 사용하는 것을 금지합니다. `BuildXMPPacket`은 최소 헤더(id="W5M0MpCehiHzreSzNTczkc9d")를 생성하며, 이 헤더에는 해당 속성이 포함되지 않습니다. 이는 모든 PDF/A 구성 요소에서 자연스럽게 충족됩니다.
  • Win32 및 Win64에서 깨끗한 컴파일이 완료되었습니다. 새로운 테스트 케이스 smoke_pdfa2_limits를 사용하여 세 가지 경로를 테스트했습니다. PDF/A-2 규격을 준수하는 경우 테스트가 통과됩니다. 32768바이트 크기의 Title을 가진 PDF/A-1 규격도 통과됩니다 (§6.1.13에 해당하는 검사는 수행되지 않음). 32768바이트 크기의 Title을 가진 PDF/A-2 규격은 규격 섹션에 따른 오류 메시지와 함께 거부됩니다. 이전의 PDF/A-2/3 기준선은 변경 없이 다시 컴파일되었습니다.
  • PDF/A-2/3 프로듀서 관련 기능: v2.108 버전에서는 PDF/A-3 부록 E의 관련 파일 기능을 구현합니다 (PDF/A-3 전용 하이브리드 컨테이너 기능: Catalog /AF 배열, 파일 사양 및 /AFRelationship 키, 임베디드 파일, /Params, /CheckSum, /ModDate).

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 버전에서 이미 적용된 PDF/A-1 관련 제한 사항은 PDFACompliance 설정이 비어 있지 않은 경우 계속 적용됩니다. v2.106 버전에서는 이러한 동작을 확인하고, 모든 PDF/A 규격에 대한 통합된 섹션을 참조하도록 진단 메시지를 개선했으며, HotPDF가 자연스럽게 충족하는 추가적인 PDF/A-2에서 도입된 제한된 유형을 문서화했습니다 (별도의 공개 기능은 제공하지 않습니다).
  • PDF/A-1은 6가지 동작(실행/사운드/영화/폼 초기화/데이터 가져오기/JavaScript)을 금지합니다. PDF/A-2 및 PDF/A-3은 금지 목록을 13가지로 확장하며, 숨기기/OCG 상태 설정/렌더링/변환/3D 뷰로 이동 기능과 더불어 더 이상 사용되지 않는 상태 설정/무효 작업 유형을 추가합니다. `AddLaunchLink`는 계속해서 문제를 발생시키며, `HotPDF`에는 다른 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 프로듀서 관련 기능 개선: v2.107은 ISO 19005-2 §6.1.13에서 정의된 구현 제한 사항을 적용합니다 (정수/실수/문자열/이름 바이트 범위, q/Q 중첩, DeviceN 색상, CID, 페이지 경계) + §6.4.2 XFA + §6.2.11 Type 3 / .notdef에 대한 엄격한 규칙을 적용합니다. v2.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-2 / PDF/A-3 사양에서 명시적으로 허용하는 기능을 v2.101-104 버전의 PDF/A-1에서 제한적으로 완화했습니다.
  • PDFACompliance 속성은 PDF/A-1의 '' / 'A' / 'B' 값 외에 6개의 새로운 값을 추가로 허용합니다. 즉, '2A' / '2B' / '2U' (PDF/A-2 레벨 A / B / U) 및 '3A' / '3B' / '3U' (PDF/A-3 레벨 A / B / U)를 지원합니다. 레벨 U는 PDF/A-2에서 도입된 새로운 "유니코드 보존 전용" 단계로, 시각적 텍스트와 유니코드 추출이 가능한 텍스트를 제공하며, 태그된 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`는 이제 PDFACompliance가 PDF/A-1로 설정된 경우에만 투명한 알파 값 또는 Normal이 아닌 블렌드 모드에서 오류를 발생시킵니다. PDF/A-2 / PDF/A-3 §6.4에서는 투명도를 명시적으로 허용하며, OutputIntent 존재 여부 및 PDF 1.4에서 정의된 모든 블렌드 모드와 같은 별도의 요구 사항이 있습니다. 따라서 PDFACompliance가 '2*' 또는 '3*'로 설정된 경우, 해당 호출은 오류 없이 진행됩니다.
  • v2.104 파일 첨부 제한 완화: `AddFileAttachmentAnnotation` 함수는 이제 PDF/A-1 표준의 엄격한 규정을 준수하지 않는 경우에만 오류를 발생시킵니다. PDF/A-2 §6.3.1에서는 3D, 오디오, 화면, 비디오 어노테이션 유형만 금지하며, 파일 첨부는 허용됩니다. 파일 첨부는 PDF/A-3의 부록 E에서 정의하는 관련 파일 하이브리드 워크플로우의 기반이 됩니다. 나머지 v2.104 어노테이션/액션 제한(오디오, 비디오 어노테이션; 실행 액션)은 여전히 모든 PDF/A 표준에서 공유되는 §6.3.1 및 §6.5.1의 금지 사항에 따라 적용됩니다.
  • 새로운 THotPDF 도우미 메서드인 PDFAPart, PDFAConformanceLevel, IsPDFA1Strict, IsPDFA2OrLater를 통해 값 분기를 더욱 효율적으로 사용할 수 있습니다. 기존 v2.101-104 PDF/A 관련 기능은 이제 이러한 도우미 메서드를 사용하여 코드 가독성을 높이고, 상황에 따라 PDF/A-2 또는 PDF/A-3로 전환하도록 안내하는 명확한 오류 메시지를 제공합니다.
  • Win32 및 Win64에서 깨끗한 컴파일이 완료되었습니다. v2.101-104 기준 테스트(smoke_pdfa1_compliance / smoke_pdfa1_forbidden / smoke_pdfa1_annot_action)는 변경 사항 없이 다시 컴파일되었습니다. 새로운 smoke 테스트인 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 추가, 더 이상 사용되지 않는 동작 및 아무 동작도 하지 않는 동작 제거). 또한 주석 유형 제한을 조정했습니다 (3D 및 Screen 추가, FileAttachment 제거). v2.107 버전에서는 ISO 19005-2 §6.1.13의 구현 제한 사항 및 XFA 관련 제한 사항을 적용했습니다. v2.108 버전에서는 PDF/A-3 부록 E의 관련 파일 (하이브리드 컨테이너 PDF)을 구현했습니다.

2026-05-19 Version 2.104.0

  • PDF/A-1 프로듀서 관련 수정 사항 (4/4): 파일 첨부, 오디오, 비디오와 같은 금지된 주석 유형 및 런치 액션 하위 유형(§6.5.2, §6.6.1)을 수정했습니다. v2.104 버전에서, 2026년 5월 19일 PDF/A-1 감사(.superpowers/specs/2026-05-19-pdfa1-compliance-audit.md)에서 식별된 17가지 프로듀서 관련 문제를 모두 해결했습니다. 여기에는 주요 문제 4가지(§5, §6.7.11 식별, §6.1.3 암호화 금지, §6.2.2 출력 의도, §6.4 투명성)와 다양한 금지 기능 제한 사항이 포함됩니다.
  • §6.5.2 금지된 주석 유형: `AddFileAttachmentAnnotation`, `AddSoundAnnotation`, `AddMovieAnnotation`은 이제 `PDFACompliance`에서 명확한 사양 섹션 진단 정보와 함께 오류를 발생시킵니다. 사양에 따르면 "FileAttachment, Sound 및 Movie 유형은 외부 콘텐츠 의존성과 보관 파일 내의 멀티미디어를 방지하기 위해 허용되지 않습니다."
  • §6.6.1 실행 동작: `AddLaunchLink` 함수는 이제 `PDFACompliance`에서 오류를 발생시키며, §6.6.1 진단 메시지를 통해 실행 대상에 대한 정보를 제공합니다. 사양에 따르면 "Launch, Sound, Movie, ResetForm, ImportData 및 JavaScript 동작은 허용되지 않습니다." 나머지 다섯 가지 금지된 동작 유형(Sound/Movie/ResetForm/ImportData/JavaScript)은 해당 기능을 제공하는 공개 `HotPDF` 진입점이 없으므로, 명시적인 제한 없이 자연스럽게 해당 조건을 만족합니다.
  • PDFUACompliance 및 PDFACompliance 기능이 결합되어 이제 모든 PDF/A 형식에서 올바르게 작동합니다. 이 두 가지 옵션은 계층적으로 적용되며, Level A는 PDFUACompliance 기능을 자동으로 활성화합니다. 두 가지 기능 모두 자체적인 섹션별 제한 사항을 적용합니다(PDF/UA의 경우 Suspects/Tabs/Lang, PDF/A의 경우 Encrypt/Transparency/Annot/Action)이며 서로 간섭하지 않습니다.
  • 감사 종료 요약: HotPDF가 구조적으로 충족할 수 있는 모든 PDF/A-1 프로듀서 측 §6 파일 형식 요구 사항이 완료되었습니다. 호출자 책임(§6.1.5 Info-XMP 동등성, §6.2.3.3 색상 공간 ↔ 출력 의도 일치, §6.3 글꼴 관련 사항은 v2.74-v2.86 PDF/UA 작업에서 이미 대부분 처리됨)은 PDF/UA-1의 해당 호출자 책임과 일치합니다.
  • Win32 및 Win64에서 깨끗한 컴파일이 완료되었습니다. v2.103 버전에서 smoke_pdfa1_forbidden 파일은 깨끗하게 재컴파일되었습니다. 새로운 smoke 테스트인 smoke_pdfa1_annot_action은 PDFACompliance 하위의 네 가지 경로(AddFileAttachmentAnnotation, AddSoundAnnotation, AddMovieAnnotation, AddLaunchLink)를 모두 실행하며, 각 호출이 §6.5.2 또는 §6.6.1 진단 오류를 발생시키는 것을 확인합니다.
  • PDF/A-1 프로듀서 표면이 이제 완전히 감사 검사를 완료했습니다. 향후 PDF/A-2 (ISO 19005-2:2011 기반, 투명도 및 레이어 지원) 및 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 ExtGState /TR 전송 함수 관련 수정 (누락 사항 #14). 기존 HotPDF 프로듀서 경로와 관련된 두 가지 §6 항목은 코드 변경 없이도 자연스럽게 충족됩니다. 이는 LZW 필터 (HotPDF는 작성 과정에서 FlateDecode만 사용) 및 이미지 /Interpolate (HotPDF는 /Interpolate을 절대 사용하지 않음)입니다. 이러한 내용은 이제 감사 보고서에 자동으로 충족된다는 내용으로 기록되었습니다.
  • §6.4 투명도는 알파 값이 1.0이 아닌 경우와 Normal/Compatible 블렌드 모드가 아닌 경우를 금지합니다. RegisterExtGState는 이제 PDFACompliance에 의해 제어되며, fill 알파 값이 1보다 작으면 오류가 발생합니다 (PDF/A-1은 /ca = 1.0을 요구함). stroke 알파 값이 1보다 작으면 오류가 발생합니다 (/CA = 1.0). `Normal` 또는 `Compatible`이 아닌 블렌드 모드를 사용하면 오류가 발생합니다. 이 세 가지 오류 모두 해당 규격 섹션과 문제 값에 대한 정보를 제공합니다. 기본 ExtGState (알파 키가 없고 BM이 없는 경우) 및 명시적으로 허용되는 값 (알파 값이 1.0인 경우, Normal / Compatible BM)은 변경되지 않고 그대로 유지됩니다.
  • §6.2.8 ExtGState에서는 /TR 전송 함수 키를 사용하지 않도록 금지합니다 (더 이상 사용되지 않으며, PDF/A-1에서는 /TR2만 사용 가능하며, 값은 /Default여야 하며, 심지어 그렇게 사용하는 것조차 권장되지 않습니다). RegisterTransferFunctionState는 이제 PDFACompliance에서 오류를 발생시키며, 명확한 진단 정보를 제공합니다. PDF/X 워크플로우에 전송 함수가 필요한 사용자는 PDFACompliance 모드 외부에서 해당 기능을 계속 사용할 수 있습니다.
  • §6.1.10 LZW + §6.2.4 보간: 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 버전에서는 §6.5.2에서 금지된 어노테이션 유형(FileAttachment, Sound, Movie)과 §6.5.3의 어노테이션 규칙 (/F /AP) 및 §6.6.1에서 금지된 액션 유형(Launch, Sound, Movie, ResetForm, ImportData, JavaScript)과 §6.9의 폼 필드 규칙 (/A /AA + /NeedAppearances)을 수정했습니다. v2.104 버전이 적용되면 PDF/A-1 프로듀서 기능은 완전히 감사 검토를 완료합니다.

2026-05-19 Version 2.102.0

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 식별, Title/Lang의 엄격한 적용, 암호화 충돌 방지)을 구현했습니다. v2.102부터 v2.104까지는 색상 관리, 투명도, 글꼴, 주석/액션 관련 나머지 문제들을 해결했습니다.
  • 새로운 `PDFACompliance: AnsiString` 속성은 '' (비활성화, 기본값), 'A' (레벨 A: 시각 + 태그 포함 PDF + 접근성), 또는 'B' (레벨 B: 시각 보존만) 값을 허용합니다. 유효하지 않은 값은 EndDoc 시점에 오류를 발생시킵니다. ISO 19005-1:2005 §5에 따른 준수 레벨을 따릅니다.
  • PDFACompliance를 'A'로 설정하면 PDFUACompliance가 자동으로 활성화됩니다 (레벨 A는 §6.8의 태그된 PDF 요구 사항을 상속하며, 이는 PDF/UA-1의 §7 논리적 구조 요구 사항과 일치합니다). 두 기능은 충돌 없이 함께 사용할 수 있습니다. v2.94 PDF/UA-1 언어/제목/의심 항목 기능은 v2.101 PDF/A 보안 기능 위에 추가됩니다.
  • 이 두 가지 수준 중 하나를 설정하면 `FEnableXMPMetadata`가 자동으로 활성화되어 문서에 필수적인 `/Metadata` XMP 스트림이 포함됩니다. §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에서는 XMP의 Info/Title에 dc:title이 필요함). 언어 엄격성은 v2.94의 PDFUACompliance 동작과 동일하며 (§6.8.4, 레벨 A), 따라서 작성자는 'en'으로 자동 설정되는 대신 실제 BCP-47 태그를 선택해야 합니다.
  • 암호화 충돌 방지: §6.1.3에 따라 파일 트레일러에는 "/Encrypt"가 포함되어서는 안 됩니다. EnableEncrypt(소유자 암호/사용자 암호/보호 설정이 변경될 때 호출되는 내부 항목)는 PDFACompliance가 비어 있지 않은 경우 명확한 오류 메시지를 발생시킵니다. EndDoc은 동일한 경로를 통해 충돌을 보고하므로 호출자는 직렬화 전에 실패를 확인할 수 있습니다.
  • 호출 측의 책임에는 여전히 다음 사항이 포함됩니다. 유효한 PDF/A-1 출력 의도를 ICC 프로필과 함께 생성합니다 (v2.102 관련), 투명성을 피합니다 (v2.103), 금지된 주석/작업 유형을 사용하지 않습니다 (v2.104), 그리고 레벨 A에 대한 실제 의미론적 구조 트리를 작성합니다 (v2.96-v2.99의 태그된 PDF 도우미에서 다루어짐).
  • Win32 및 Win64에서 깨끗하게 컴파일되었습니다. v2.100 버전의 기본 smoke_pdfua_link_contents 테스트가 깨끗하게 재컴파일되었습니다. 새로운 smoke 테스트인 smoke_pdfa1_compliance는 레벨 A 및 레벨 B PDF를 모두 생성하며, 세 가지 검증 경로를 실행합니다 (잘못된 레벨 Z, 빈 Title, 암호화 및 PDFACompliance 충돌). 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

  • 2026-05-19 감사에서 발견된 PDF/UA-1 §7.18.5 링크-주석 /Contents 관련 미흡한 부분을 수정했습니다. v2.95 버전에서 AddURILink에 Description 기능을 추가했으며, v2.100 버전에서는 나머지 세 가지 링크 생성 기능(AddGoToLink: 문서 내 이동, AddGoToRLink: 파일 간 이동, AddLaunchLink: 외부 파일 실행)에도 동일한 대체 설명 기능을 적용했습니다.
  • 각 헬퍼 함수는 선택적인 `const Description: AnsiString = ''` 매개변수를 추가합니다. 이 매개변수가 비어 있지 않으면, 주석 딕셔너리에 `/Contents (Description)` 항목이 포함됩니다. `PDFUACompliance` 모드에서는, Description이 비어 있으면 오류가 발생하며, 문제 링크 대상을 명확하게 식별하여 대체 설명이 누락된 경우를 방지합니다. 기본적으로 비워두면 PDFUACompliance 모드 외부에서 이전 버전과의 호환성을 유지합니다.
  • PDF/UA-1 §7.18.5에 명시된 대로, "링크는 ISO 32000-1:2008의 14.9.3에 설명된 대로, Contents 키를 통해 대체 설명을 포함해야 합니다." 이 규격은 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 baseline smoke_pdfua_figure가 깨끗하게 재컴파일되었습니다. 새로운 smoke 테스트인 smoke_pdfua_link_contents는 0페이지에 세 개의 링크 주석을 포함하는 2페이지 분량의 문서를 생성합니다 (1페이지로 이동, 'companion.pdf'로 이동, 'readme.txt' 실행). 또한, 모든 세 개의 링크 주석에 대해 empty-Description PDFUACompliance 예외 경로를 테스트합니다. Python 검증기는 각 링크 주석이 /Subtype /Link를 포함하고, 일치하는 /S가 /GoTo (또는 /GoToR 또는 /Launch) 액션 유형이며, 제공된 Description과 일치하는 /Contents 값을 가지고 있는지 확인합니다.
  • PDF/UA-1 프로듀서 측면의 기능 개선 사항 요약: v2.100 버전에서, 네 가지 링크 주석 항목 모두 이제 §7.18.5 조항을 만족합니다. 또한 v2.94 버전에서 수행된 감사 결과(Suspects, Tabs, Lang), v2.95 버전(URI Contents, Bit 10, ID), 그리고 v2.96부터 v2.99까지의 태그가 있는 PDF에 대한 의미론적 지원 기능(Heading, List, Table, Figure)과 결합하여, HotPDF의 PDF/UA-1 프로듀서 측면 기능은 이제 사양을 엄격하게 준수하는 래퍼 계층과 사용자 친화적인 API 계층 모두에서 감사 완료되었습니다.

2026-05-19 Version 2.99.0

  • PDF/UA-1 §7.3 (그래픽)을 위한 태그된 PDF 의미 체계 도우미 시리즈의 네 번째이자 마지막 부분으로, `BeginTaggedFigure(Parent, AltText, BBox): FigureElem` 및 `EndTaggedFigure`가 추가되었습니다. 이 기능은 호출자가 제공하는 드로잉 작업(이미지 XObject, 벡터 경로, 채워진 사각형)을 필수적인 `/Alt` 레이아웃 속성과 선택적인 `/BBox` 레이아웃 속성을 가진 Figure 구조 요소 내부에 포함시킵니다.
  • `/Alt` 필드는 필수이며, 기본값으로 빈 값을 사용할 수 없습니다. PDF/UA-1 §7.3에 명시된 대로, "그림 태그에는 그림 태그로 표시된 콘텐츠를 나타내는 대체 표현 또는 대체 텍스트가 포함되어야 합니다." 빈 `AltText` 필드는 명확한 오류 메시지를 발생시키며, 호출자가 `/ActualText` ( `/Alt`가 아닌)가 적절한 대체 텍스트 메커니즘인 경우 v2.88 버전의 6개 인수를 사용하는 `AddStructureElement` 함수를 사용하도록 안내합니다.
  • 선택적인 BBox는 기본 사용자 공간에서 도형의 경계 상자를 설명하는 4개의 값으로 구성된 [llx, lly, urx, ury] 배열이며, ISO 32000-1 14.8.5.4.5에 따라 /A << /O /Layout /BBox [...] >>로 첨부됩니다. BBox 속성을 완전히 건너뛰려면 빈 배열을 전달하십시오. 잘못된 길이의 BBox(1/2/3/5개 이상의 요소)는 사양에 따른 사각형 레이아웃을 기준으로 오류를 발생시킵니다.
  • 일반적인 워크플로우는 다음과 같습니다: `Fig := Doc.BeginTaggedFigure(Root, 'Company logo: arrow pointing right', [72, 600, 200, 720]); ... 그림 내용을 그립니다 ... Doc.EndTaggedFigure;` 이 Figure는 다른 v2.90 BeginTaggedContent 경로와 동일한 MCID / ParentTree 연결을 사용하지만, `/Alt` 및 `/BBox` 속성이 자동으로 연결됩니다.
  • 이 변경 사항은 감사 보고서에서 언급된 PDF/UA-1 §7.3의 호출자 책임 관련 문제를 해결합니다. 태그가 지정된 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에서 깨끗하게 컴파일되었습니다. v2.98 버전의 기본 smoke_pdfua_table이 깨끗하게 재컴파일되었습니다. 새로운 smoke smoke_pdfua_figure은 두 개의 Figure 구조 요소(하나에는 /Alt 및 /BBox가 포함되고, 다른 하나에는 /Alt만 포함됨)를 생성하며, 또한 empty-AltText 및 malformed-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`은 필수적인 /Scope 속성을 가진 TH 셀을 생성합니다. `EmitTaggedTableCell(TR, X, Y, Text): TDElem`은 TD 데이터 셀을 생성합니다. 모든 다섯 가지 태그 유형(테이블, TR, TH, TD 및 속성 객체)은 사양을 준수합니다.
  • /Scope 속성(ISO 32000-1 14.8.5.7 표 350)은 필수이며, 기본값은 없습니다. 유효한 값은 `Row`, `Col` 또는 `Both`입니다. 유효하지 않은 Scope 문자열은 사양을 기준으로 오류를 발생시킵니다. PDF/UA-1 §7.5에서는 다음과 같이 명시합니다. "TH 유형의 구조 요소는 Scope 속성을 가져야 합니다. 표의 구조가 헤더 및 ID를 통해 결정할 수 없는 경우, TH 유형의 구조 요소는 Scope 속성을 가져야 합니다." 헬퍼의 서명에 Scope를 강제 적용하면 Scope가 누락되어 발생하는 오류를 방지할 수 있습니다.
  • 범위 직렬화는 표준 속성 객체 형식을 따릅니다: `/A << /O /Table /Scope / >>` (ISO 32000-1 14.7.5.3 클래스 맵에 정의된 대로), 따라서 소비자 리더는 이를 테이블 네임스페이스의 속성으로 인식합니다. 이는 v2.97 버전의 목록 `/A << /O /List /ListNumbering ... >>` 속성과 동일한 패턴입니다.
  • 테이블(Table)과 TR은 페이지의 구조를 정의하는 컨테이너이며, 콘텐츠가 표시되지 않습니다. 하지만 TH와 TD는 텍스트를 포함하므로 BeginTaggedContent, TextOut, EndTaggedContent 과정을 거칩니다. 각 TH 및 TD 셀은 자체 MCID, 페이지 콘텐츠 스트림의 BDC 연산자 및 ParentTree 항목을 갖습니다. Helper 함수는 추가 속성을 연결하려는 사용자를 위해 해당 셀의 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')); ...` 이는 각 셀에 대해 v2.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 버전의 baseline smoke_pdfua_list가 깨끗하게 재컴파일되었습니다. 새로운 smoke smoke_pdfua_table은 3행짜리 테이블(1개의 헤더 + 2개의 데이터 행)을 생성하며, 3개의 TH 셀(Scope=Col)과 6개의 TD 셀을 포함합니다. 또한, 유효하지 않은 Scope 예외를 테스트합니다. Python 검증기는 모든 Table > TR > TH/TD 구조를 확인하며, 각 TH에 대해 /Scope /Col 속성이 있는지 확인합니다.

2026-05-19 Version 2.97.0

  • PDF/UA-1 §7.6 목록 지원 기능을 추가했습니다. 이 기능은 태그가 지정된 PDF의 의미 체계 지원 기능 시리즈의 두 번째 부분입니다. `BeginTaggedList(Parent, NumberingStyle): ListElem`은 ISO 32000-1 14.8.5.5에 따라 /A << /O /List /ListNumbering /<Style> >> 속성 객체를 사용하여 L 구조 요소(ListElem)를 생성합니다. `EmitTaggedListItem(ListElem, LblX, LblY, LabelText, BodyX, BodyY, BodyText): LIElem`은 표시되는 레이블과 본문 텍스트 모두에 대해 마크된 콘텐츠를 포함하는 완전한 LI > {Lbl, LBody} 하위 구조를 생성합니다.
  • NumberingStyle 매개변수는 8개의 PDF/UA-1 / ISO 32000-1 사양 이름 중 하나를 허용합니다: `None`, `Decimal`, `UpperRoman`, `LowerRoman`, `UpperAlpha`, `LowerAlpha`, `Circle`, `Disc`. 유효하지 않은 스타일 이름이 제공되면 오류가 발생하며, 문제 값과 전체 사양 세트가 안내 정보로 제공됩니다. 빈 문자열을 사용하면 /ListNumbering이 완전히 생략되므로 호출자는 커밋하기 전에 사용자 정의 속성 객체를 연결할 수 있습니다.
  • PDF/UA-1 §7.6에 따르면, 순서가 있는 목록은 명시적인 `/ListNumbering` 속성이 필요하며, 순서가 없는 목록은 `None` 또는 글머리 기호 중 하나를 사용할 수 있습니다. 이 도구는 이러한 규칙을 강제하지 않습니다. 스타일을 선택하는 것은 호출자의 책임이며, 이는 표시되는 콘텐츠와 일치해야 합니다.
  • 일반적인 워크플로우는 다음과 같습니다: `Lst := Doc.BeginTaggedList(Root, 'Decimal'); Doc.EmitTaggedListItem(Lst, 72, 750, WideString('1.'), 96, 750, WideString('First item')); ...` 각 목록 항목은 v2.90 버전의 여섯 줄짜리 LI + Lbl-BDC-TextOut-EMC + LBody-BDC-TextOut-EMC 체인을 대체하는 하나의 호출입니다.
  • Lbl 및 LBody 자식 요소는 모두 BeginTaggedContent를 거치므로 각각 자체 MCID 및 ParentTree 항목을 갖습니다. EmitTaggedListItem 도우미 함수는 LI 구조 요소를 반환하며, 이를 통해 호출자는 중첩된 LI 자식 요소, /Alt 또는 /Lang 속성을 추가할 수 있습니다.
  • 이 변경 사항은 감사 보고서에서 PDF/UA-1 §7.6에 명시된 호출자 책임 영역을 해결합니다. 나머지 태그가 포함된 PDF의 의미 체계 지원 기능(v2.98 이상): §7.5를 다루는 테이블 지원 기능 (테이블 / TR / TH / TD 및 /Scope 속성), §7.3을 다루는 그림 지원 기능 (그림 + /Alt + /BBox 속성).
  • Win32 및 Win64에서 깨끗하게 컴파일되었습니다. v2.96 버전의 baseline smoke_pdfua_heading이 깨끗하게 재컴파일되었습니다. 새로운 smoke smoke_pdfua_list는 3개의 항목으로 구성된 숫자 순서 목록과 2개의 항목으로 구성된 번호 없는 목록을 생성하며, 잘못된 스타일 예외 경로를 테스트합니다. Python 검증기는 두 개의 /S /L StructElems가 있으며, 각각 다른 /ListNumbering 속성 값을 가지며, 첫 번째 순서 목록의 LI 요소에는 3개의 LI 자식과 Lbl/LBody 자식이 있는지 확인합니다.

2026-05-19 Version 2.96.0

  • PDF/UA-1 §7.4을 위해 `EmitTaggedHeading(Level, Parent, X, Y, Text)`라는 고수준 헬퍼 함수를 추가했습니다. 이 함수를 한 번 호출하면 현재 페이지의 `/H1`에서 `/H6`까지의 완전한 구조 요소가 생성되고, 해당 텍스트가 표시됩니다. 이 헬퍼 함수는 페이지별 MCID를 할당하고, BDC 연산자를 실행한 다음 TextOut을 실행하고, EMC를 실행하며, 적절한 `/H<Level>` 역할을 가진 StructElem을 생성하고, 이를 `/ParentTree`에 연결합니다. 이 함수는 v2.90에서 사용하던 세 줄로 이루어진 BeginTaggedContent + TextOut + EndTaggedContent 패턴을 일반적인 헤딩의 경우에 대체합니다.
  • 레벨 매개변수는 1부터 6까지의 값을 허용합니다(기본 헤딩 세트). 유효 범위를 벗어난 레벨 값은 명확한 오류 메시지와 함께 예외를 발생시킵니다. PDF/UA-1 §7.4.3에서는 사용자가 정의한 H7+ 태그를 허용하지만, 이러한 태그는 드물게 사용됩니다. 필요한 경우, 호출자는 명시적인 BeginTaggedContent('H7', ...) 시퀀스를 사용해야 합니다.
  • 호출자가 헬퍼 함수가 반환한 후에도 속성 추가(예: /Lang, 장식용 헤더의 /Alt 등)를 체인 방식으로 수행할 수 있도록 StructElem 헤더를 반환합니다.
  • 일반적인 워크플로우: `Doc.EmitTaggedHeading(1, RootElem, 72, 750, WideString('Chapter 1'));` 이 코드는 이제 여러 줄로 구성된 BDC + TextOut + EMC + AddStructureElement 코드를 완전히 대체합니다.
  • 이것은 계획된 "태그가 지정된 PDF 의미 체계 도우미" 시리즈의 첫 번째 부분이며, v2.95 PDF/UA-1 래퍼의 종료를 따릅니다. 향후 버전(v2.97 이상)에서는 목록(L / LI / Lbl / LBody) 및 테이블(Table / TR / TH / TD with /Scope) 도우미를 다루어 감사 보고서의 §7.5 및 §7.6에서 언급된 호출자 책임 영역을 해결할 예정입니다.
  • Win32 및 Win64에서 깨끗하게 컴파일되었으며, v2.95 기준이 다시 깨끗하게 컴파일되었습니다. 새로운 smoke 테스트 `smoke_pdfua_heading`은 세 개의 제목(H1/H2/H3)을 생성하고, Level=7 범위 검사 예외 경로를 테스트합니다. Python 검증기는 압축된 페이지 콘텐츠 스트림에서 세 개의 /S /H StructElems 및 해당 /H BDC 연산자를 확인합니다.

2026-05-19 Version 2.95.0

  • PDF/UA-1 감사 완료: v2.94 감사에서 식별된 세 가지 남은 제작자 측의 문제점을 해결했습니다(§7.18.5 링크 내용, §7.16 암호화 비트 10, §7.9 StructElem ID). PDF/UA-1 제작자 관련 기능은 이제 사양을 완전히 충족하며, 원래 감사에서 식별된 여섯 가지 문제점 모두 v2.94 및 v2.95 버전을 통해 해결되었습니다.
  • §7.18.5 링크 내용(중요): `AddURILink(Rect, URL, Description='')` 함수에 세 번째 매개변수인 `Description`이 추가되었으며, 이 매개변수가 비어 있지 않으면 어노테이션의 `/Contents` 키에 제공된 대체 설명이 채워집니다. PDF/UA-1 §7.18.5에서는 이를 필수 사항으로 규정합니다. "링크는 `/Contents` 키를 통해 대체 설명을 포함해야 합니다." PDFUACompliance 모드에서는 빈 `Description`이 제공될 경우 명확한 오류 메시지가 표시되어 모든 링크에 화면에서 읽을 수 있는 텍스트가 함께 제공됩니다. 이전 버전과의 호환성을 위해 PDFUACompliance 모드 외부에서는 `Description`의 기본값은 빈 문자열입니다.
  • §7.16 암호화 비트 10 (MED): PDFUACompliance가 True이고 문서가 암호화된 경우 (EnableEncrypt를 통해), HotPDF는 자동으로 `ProtectFlags := ProtectFlags or $200`을 수행합니다 (비트 10은 "보조 기술을 사용한 텍스트 및 그래픽 추출"을 의미). PDF/UA-1 §7.16에 따르면: "암호화된 규격 준수 파일은 암호화 사전 딕셔너리에 P 키를 포함해야 합니다. P 키의 10번째 비트 위치는 True여야 합니다." 이 비트가 없으면 화면 읽기 프로그램은 암호화된 PDF에서 콘텐츠를 추출할 수 없으므로 접근성이 저하됩니다. 이 수정 사항은 조건부로 적용되며, PDFUA가 아닌 암호화의 경우 호출자가 제공한 플래그는 변경되지 않습니다.
  • §7.9 StructElem ID (낮은 부분): 새로운 7개의 인수를 받는 `AddStructureElement` 함수가 추가되었습니다. 이 함수는 비어 있지 않은 `IDStr` 매개변수를 받아 구조 요소의 `/ID` 키를 설정합니다. 이 기능은 발급된 ID 목록을 내부적으로 관리하며, 충돌이 발생하면 오류를 발생시켜 중복된 노트 ID가 생성되는 것을 방지합니다. (이는 교차 참조 링크와 노트 간의 연결 및 보조 기술 사용 시 혼란을 야기할 수 있습니다.) 사양에 따르면: "각 노트 태그는 ID 키에 고유한 항목을 가져야 합니다."
  • EnableEncrypt 리팩토링: 원래 기능은 이제 `EnableEncryptInternal`에 포함되어 있으며, 공개 API인 `EnableEncrypt`는 6줄로 구성된 래퍼 함수로, 먼저 PDF/UA-1 비트 10 스탬프를 적용한 다음, 나머지 처리를 위임합니다. v2, v4, v5 암호화 브랜치는 변경되지 않았으며, 기존 암호화된 PDF를 사용하는 클라이언트는 PDFUACompliance를 명시적으로 활성화하지 않는 한 동일한 출력을 유지합니다.
  • 검증 범위: 새로운 `smoke_pdfua_gap_closure` 테스트 항목이 추가되었습니다. 여기에는 §7.18.5 (설명과 함께 연결된 항목) 및 §7.9 (고유한 ID를 가진 두 개의 Note 구조 요소 및 충돌 시도)가 포함됩니다. 검증기는 `/Contents` 속성이 존재하고 설명과 일치하는지, 그리고 두 개의 고유한 Note `/ID` 값이 존재하는지 확인합니다. 암호화 관련 수정 사항은 감사 보고서에 자세히 설명되어 있으며, 암호화된 PDF 파일에 대한 검증은 향후 더 큰 규모의 암호화 테스트 재작성에서 다루기로 예정되어 있습니다.
  • v2.95 버전이 출시되면서, 2026-05-19 PDF/UA-1 감사(`superpowers/specs/2026-05-19-pdfua-compliance-audit.md`)에서 식별된 6가지 문제점이 모두 해결되었습니다. HotPDF의 PDF/UA-1 준수 기능은 이제 래퍼 레이어에서 엄격하게 준수하며, 이는 §5 메타데이터, §6 준수, §7.1 카탈로그 요구 사항, §7.2 언어, §7.16 암호화, §7.18.3 탭, §7.18.5 링크 내용, §7.9 노트 ID를 포함합니다. 의미론적 구조 트리 결정(제목 계층 구조, 목록 중첩, 테이블 TH/범위, 그림/대체 텍스트 품질)은 항상 호출자(caller)의 책임입니다.

2026-05-19 Version 2.94.0

  • PDF/UA-1 (ISO 14289-1:2014) 생산자 측 규정 준수 감사 후속 조치: v2.87의 기본적인 선택 가입 옵션에서 다루지 못했던 세 가지 실제 규정 준수 문제를 해결했습니다. 감사는 HotPDF v2.93의 출력 결과를 §7의 모든 파일 형식 요구 사항 조항과 비교하여 여섯 가지 생산자 문제를 확인했으며, 이번 버전에서는 EndDoc 단계의 세 가지 문제를 해결합니다 (의심스러운 키, 주석이 포함된 페이지 탭, 언어 엄격성). 나머지 세 가지 문제 (링크 내용, 암호화 비트 10, StructElem ID)는 v2.95-v2.97 버전에서 해결될 예정입니다.
  • §7.1 의심 항목 (심각): 카탈로그의 `MarkInfo` 사전이 이제 `PDFUACompliance`가 True일 때 `/Suspects false`를 출력합니다. 사양에 따르면 "이 국제 표준을 준수한다고 주장하는 파일은 `Suspects` 값을 `false`로 가져야 합니다." veraPDF와 유사한 검사기는 키의 존재 여부를 확인하며, 단순히 키가 없는 경우를 확인합니다. v2.93에서는 해당 키를 완전히 제거하여 "카탈로그 `MarkInfo`에 `Suspects` 항목이 포함되어 있지 않습니다"라는 오류가 발생했습니다.
  • §7.18.3 탭 (중요도: 중간): 이제 `EndDoc`은 모든 페이지를 순회하며, `/Annots` 배열이 비어 있지 않고 아직 `/Tabs`를 선언하지 않은 페이지에 `/Tabs /S`를 추가합니다. 이는 사양에 따른 것입니다. ("각 페이지에 주석이 포함되어 있으면 해당 페이지의 페이지 딕셔너리에 'Tabs' 키가 포함되어야 하며, 그 값은 'S'여야 합니다.") 이 기능은 `PDFUACompliance` 설정에서만 작동하며, `THPDFPage.SetTabsOrder`를 통해 `/Tabs`를 명시적으로 설정한 호출자는 해당 설정을 유지합니다.
  • §7.2 Lang (중요): `PDFUACompliance=True`를 사용하면서 `Doc.Lang`이 비어 있는 경우, 이제 명확한 오류 메시지와 함께 예외가 발생합니다. 이전 버전(v2.94 이전)에서는 영어가 아닌 문서를 잘못 식별했습니다 (중국어/아랍어/일본어 등 모든 콘텐츠가 잘못된 BCP-47 태그를 생성하여, 화면 읽기 프로그램이 발음을 전환하는 데 사용되었습니다). 이제 호출자는 문서 언어를 명시적으로 선언해야 합니다. 일반적인 사용 예: `Doc.Lang := 'en-US'`, `'zh-CN'`, `'ar-SA'` 등.
  • 기존 PDFUACompliance 기능을 사용하는 경우, BeginDoc/EndDoc 호출 전에 `Doc.Lang := '...'`을 추가해야 합니다. smoke_pdfua_compliance, smoke_pdfua_alt_actualtext, smoke_pdfua_annot_structparents, smoke_pdfua_tagged_content의 네 가지 샘플 테스트는 `Doc.Lang := 'en-US'`로 설정되었으며, PDFUACompliance를 사용하지 않는 사용자는 영향을 받지 않습니다.
  • `smoke_pdfua_compliance_verify.py` 스크립트에서 이제 Catalog MarkInfo 딕셔너리에 `/Suspects false`를 확인하고, `smoke_pdfua_annot_structparents_verify.py` 스크립트에서는 주석이 포함된 페이지에서 `/Tabs /S`를 확인합니다. 두 스크립트 모두 생성된 PDF 파일에 대해 전체 테스트를 수행합니다.
  • 감사 보고서: 모든 21개의 §7 파일 형식 조항을 다루는 PDF/UA-1 준수 감사 보고서가 `.superpowers/specs/2026-05-19-pdfua-compliance-audit.md`에 보관되어 있습니다(프로젝트 로컬, 커밋되지 않음). 보고서는 각 조항을 'HotPDF가 자동으로 충족', '헬퍼 API를 사용한 호출자 책임', 또는 '실제 제작자 간의 차이'로 분류하고, v2.95+ 로드맵을 위해 남은 문제점을 심각도에 따라 순위를 매겼습니다.

2026-05-19 Version 2.93.0

  • `RegisterColorConversionLUT3D(GridR, GridG, GridB, OutputComponents, Samples, BitsPerSample=8, Order=1): THPDFStreamObject` 함수가 추가되었습니다. 이 함수는 v2.52 버전의 Function Type 0 기본 함수를 기반으로 하며, 일반적인 3개의 입력 값을 사용하는 색상 관리 LUT(Look-Up Table) 사용 사례를 위한 고수준 래퍼입니다. 이 함수는 내부적으로 표준 `/Domain=[0,1]*3 + /Range=[0,1]*OutputComponents + /Size=[GridR, GridG, GridB]` 배열을 생성하고 `RegisterSampledFunction` 함수에 전달합니다.
  • 일반적인 워크플로는 ICC 프로파일 기반의 sRGB에서 Lab으로, 또는 sRGB에서 CMYK으로, 또는 RGB에서 RGB 장치 링크 변환으로 표현되며, 이는 3D LUT로 나타낼 수 있습니다. 래퍼는 각 축의 그리드 크기와 출력 구성 요소 범위를 검증합니다. 기본 RegisterSampledFunction은 BitsPerSample, Order 및 총 바이트 수를 예상되는 Sample 페이로드 크기와 비교하여 검증합니다. 일치하지 않는 버퍼가 있는 경우, 명확한 진단 메시지와 함께 오류가 발생합니다.
  • 샘플 바이트 레이아웃은 3D 그리드에서 행 우선 순서로 구성되며, R이 가장 빠르고, 그 다음 G, 마지막으로 B입니다. `BitsPerSample=8`일 때 각 셀당 `OutputComponents` 바이트가 사용됩니다. 총 바이트 수는 `GridR * GridG * GridB * OutputComponents`입니다. 더 높은 비트 심도(12, 16)의 경우, 호출자는 사양의 MSB-first 바이트 패킹 규칙에 따라 데이터를 패킹해야 합니다.
  • 사용자에게 눈에 띄는 변경 사항은 다음과 같습니다. 이제 색상 관리 워크플로우에서 17x17x17 RGB에서 CMYK로의 ICC 시뮬레이션을 한 줄로 표현할 수 있으며, 이전에 수동으로 `/Domain`, `/Range`, `/Size`를 설정하는 대신 미리 계산된 샘플 배열을 사용할 수 있습니다. 반환된 간접 `THPDFStreamObject`는 모든 함수를 사용하는 API에 연결할 수 있습니다. 예를 들어, 패턴 유형 2 축/방사형 음영 `/Func` 슬롯, `RegisterSeparationLUT`를 통한 분리 색조 변환, `/TR` 전송 함수 ExtGState, `/BG` 검정색 생성 ExtGState 등에 사용될 수 있습니다.
  • 기존의 `RegisterSampledFunction` 기능은 변경되지 않았으며, 새로운 래퍼는 간단하게 추가되었습니다. 기본값 이외의 `/Domain` 값(예: [0..100] 범위의 Lab L* 또는 [-128..127] 범위의 a*/b*) 또는 직사각형이 아닌 범위를 사용하는 사용자는 `RegisterSampledFunction`을 직접 사용해야 합니다.
  • 후보 #4의 상태: 이것은 "3D Function Type 0" 행렬 후보의 유일한 부분입니다. 이 상위 수준 래퍼는 기존의 N=3 원시 기능을 일반적인 색상 관리 사용 사례에 적합하도록 만들어줍니다. 따라서 후보 #4는 종료됩니다.

2026-05-19 Version 2.92.0

  • `RegisterHalftoneType5(ColorantNames, Halftones, DefaultHalftone, HalftoneName)` 함수가 추가되어 ExtGState `/HT` 하프톤 패밀리가 완료되었습니다. Type 5는 색상 이름(예: /Cyan, /Magenta, /Yellow, /Black, /Red, /Green, /Blue, /Gray, 그리고 등록된 Separation/DeviceN 스팟 색상)을 키로 하는 다중 구성 딕셔너리이며, 각 값은 Type 1/6/10/16 하위 하프톤에 대한 간접 참조입니다. 이제 CMYK 사전 인쇄 워크플로우에서 각 잉크에 대해 단일 ExtGState 항목에서 스크린 주파수/각도/점 모양을 개별적으로 지정할 수 있습니다.
  • 병렬 배열 시그니처: `ColorantNames`와 `Halftones`는 쌍으로 매칭되고, 길이가 동일한지 검증됩니다. 빈 색상 이름 또는 nil 값의 하프톤은 문제가 있는 인덱스와 함께 오류를 발생시킵니다. 선택적인 `DefaultHalftone`은 딕셔너리의 `/Default` 값으로 사용되며, 명시적으로 지정된 목록에 없는 모든 색상에 대해 소비자 리더가 이 값을 사용합니다 (예상치 못한 스팟 색상이 포함된 문서에서 일반적입니다).
  • 출력되는 딕셔너리 구조는 (PDF 1.7 ISO 32000-1 10.5.5.2) /Type /Halftone + /HalftoneType 5 + 선택적으로 /HalftoneName + 각 쌍에 대한 하나의 /ColorantName 항목 + 선택적으로 /Default를 포함합니다. 이 함수는 간접적인 THPDFDictionaryObject를 반환하며, 호출자는 이를 다른 하프톤 객체와 마찬가지로 v2.64의 `RegisterHalftoneState` 함수에 전달할 수 있습니다.
  • 검증: 최소한 하나의 구성 요소 또는 `DefaultHalftone`이 필요합니다 (`/Default`이 없는 빈 Type 5는 의미적으로 무의미합니다). 이 함수는 제공된 하프톤이 Type 5가 아닌지 검증하지 않습니다 (사양에서는 Type 5의 중첩을 금지함). 이는 호출자가 자기 참조 그래프를 명시적으로 구성해야 하기 때문이며, 실제 사전 인쇄 워크플로우에서는 이러한 문제가 발생하지 않습니다.
  • 사용자에게 보이는 변경 사항은 다음과 같습니다. 사전 준비 단계에서 4가지 색상의 브로셔를 게시하는 작업자가 이제 4개의 독립적인 화면을 설정할 수 있습니다 (청색: 105° / 75 lpi, 마젠타: 75° / 75 lpi, 황색: 90° / 75 lpi, 검정: 45° / 75 lpi, Type 1 스팟 함수를 통해 구현하거나, FM 스크리닝을 위해 Type 6 임계값 라스터로 대체 가능). 이러한 화면은 하나의 ExtGState 내에 묶입니다. 그런 다음, 각 채널 화면이 필요한 모든 드로잉 작업에서 동일한 ExtGState가 활성화됩니다.
  • 후보 #3 상태: 이는 ExtGState `/HT` 하프톤 패밀리의 두 번째이자 마지막 버전입니다. 모든 기능 세트(v2.64의 Type 1 스팟 함수, v2.92의 Type 5 다중 구성 요소, v2.91의 Type 6/10/16 임계값 스트림)가 이제 PDF 1.7 사양을 완전히 준수합니다. 후보 #3 개발이 완료되었습니다.

2026-05-19 Version 2.91.0

  • v2.64 버전부터 시작된 ExtGState `/HT` 래스터 하프톤 패밀리를 완성하기 위해 세 가지 임계값 스트림 하프톤 빌더를 추가했습니다. 추가된 기능은 다음과 같습니다: `RegisterHalftoneType6` (너비/높이 키를 사용하는 8비트 임계값 래스터), `RegisterHalftoneType10` (Xsquare/Ysquare를 사용하여 각도 스크린을 구현하는 8비트 임계값 래스터), 그리고 `RegisterHalftoneType16` (16비트 임계값 래스터, 고품질 사전 인쇄를 위한 65536 레벨의 정밀도).
  • 각 빌더는 호출자가 v2.64 버전의 `RegisterHalftoneState` 함수에 전달하여 ExtGState /HT 항목으로 래핑할 수 있는 간접 /Type /Halftone 스트림 객체를 반환합니다. 이는 Type 1 스팟 함수 하프톤과 동일합니다. 선택적인 /HalftoneName, /TransferFunction 또는 /TransferFunction /Identity 항목은 Type 1 패턴과 일치합니다.
  • 크기 검증: 유형 6의 경우 `len(ThresholdBytes)`는 `Width*Height`와 같아야 합니다. 유형 10의 경우 `Xsquare^2 + Ysquare^2` 조건을 만족해야 합니다 (PDF 1.7 10.5.5.4 스택된 사각형 레이아웃). 유형 16의 경우 `Width*Height*2`여야 합니다 (큰 엔디안 uint16 쌍, 호출자가 제공). 일치하지 않는 버퍼는 실제 바이트 수와 예상 바이트 수를 모두 포함하는 예외를 발생시킵니다.
  • `_HotPDFCreateHalftoneStream` 내부 도우미 함수는 각 유형별 생성 과정을 중복 제거합니다. 여기에는 간접 스트림 할당, `/Type /Halftone` 및 `/HalftoneType N` 헤더, 선택적 이름 및 전송 함수 항목, 페이로드 쓰기 및 `/Length` 스탬프가 포함됩니다. 각 공개 함수는 유형별 크기 키만 확인하고, 나머지는 전달합니다.
  • 사용자에게 보이는 변경 사항: 사용자 정의 화면 패턴(사용자 정의 점 모양, 주파수 변조 화면, 각도 셀)이 필요한 사전 인쇄 워크플로우에서 이제 HotPDF를 통해 해당 기능을 사용할 수 있습니다. 호출자는 임계값 래스터 이미지를 제공합니다(일반적으로 화면 패턴 생성기로 오프라인에서 생성). HotPDF는 PDF 사양을 준수하는 `/Type /Halftone` 스트림 객체를 생성하고 ExtGState 리소스 체인에 연결합니다.
  • PDF 1.7, ISO 32000-1의 10.5.5.3 (Type 6) 및 10.5.5.4 (Type 10) 및 10.5.5.5 (Type 16)에 대한 지원이 추가되었습니다. 또한, 하프톤이 함께 적용되는 경우, 자동으로 PDF 1.2로 업데이트됩니다.
  • 후보 #3의 상태: 이는 "ExtGState /HT 하프톤 잔여 유형" 행렬 후보의 첫 번째 부분입니다. 유형 5 다중 구성 하프톤(색상 구성 요소 이름으로 키가 지정된 딕셔너리이며, 각 채널에 대한 화면을 위해 유형 1/6/10/16 하위 딕셔너리로 위임되며, CMYK 사전 인쇄용)이 두 번째이자 마지막 부분이며 v2.92에 포함됩니다.

2026-05-19 Version 2.90.0

  • `THotPDF.BeginTaggedContent(Role, Parent): THPDFDictionaryObject` 및 `THotPDF.EndTaggedContent`라는 고수준의 마크 콘텐츠 시퀀스 도우미 기능을 추가했습니다. 이 도우미는 각 페이지에 대한 MCID를 자동으로 할당하고, 현재 페이지의 콘텐츠 스트림에 BDC 연산자를 출력하며, 지정된 부모 아래에 StructElem을 생성하고, 한 번의 호출로 `/ParentTree`에 연결합니다. 결과적으로, PDF/UA-1을 사용하는 사용자는 MCID 카운터를 수동으로 관리하지 않고도 가시 콘텐츠 단락에 태그를 지정할 수 있습니다.
  • 일반적인 사용법은 다음과 같습니다: `Para := Doc.BeginTaggedContent('P', Root); Doc.CurrentPage.TextOut(...); Doc.EndTaggedContent;` 반환된 StructElem은 AddStructureElement('Span', Para, ...)를 사용하여 하위 구조를 만들거나, v2.88 속성 경로를 통해 /Alt 및 /ActualText를 전달할 수 있습니다.
  • 새로운 THPDFPage.FNextMCID 필드는 각 페이지별 MCID 할당을 추적하며, 페이지마다 초기화됩니다 (BeginDoc 초기화 시 지연 초기화되어 0으로 설정됨). 낮은 수준의 BeginMarkedContentMCID / EndMarkedContent 연산자는 (HotPDF에서 v2.11부터 사용 가능) 명시적인 MCID 제어가 필요한 사용자를 위해 계속 제공됩니다.
  • 파이프라인 통합: `BeginTaggedContent`는 현재 페이지 콘텐츠 스트림에 "/Role > BDC"를 출력하고, `AddStructureElement(Role, Parent, PageIdx, MCID)`를 호출하여 `StructElem`을 생성하고 `RegisterMCIDForPage`를 실행합니다 (v2.119.54 버전에서 페이지 딕셔너리에 `/StructParents`를 지연적으로 추가하고 `/ParentTree`에서 페이지별 배열을 확장합니다). `EndTaggedContent`는 현재 페이지에 "EMC"를 출력합니다. 중첩은 페이지 콘텐츠 스트림의 선형 순서를 통해 `BDC/EMC` 쌍이 암시적으로 중첩되기 때문에 가능합니다.
  • PDF/UA-1 표준을 준수하는 문서에서, 이제 모든 보이는 단락, 제목, 텍스트 영역 또는 그림 설명을 그래픽 호출을 둘러싼 두 줄로 의미론적 구조를 사용하여 태그할 수 있습니다. veraPDF는 생성된 페이지 콘텐츠 및 마크업 콘텐츠 시퀀스를 처리하며, 구조 트리 연결을 지원합니다. 보조 기술은 문서 개요를 따라 마크업 콘텐츠로 이동하고, 역할과 텍스트를 알려줍니다.
  • 후보 #1 상태: 네 번째이자 최종 단계. PDF/UA-1 관련 기능은 이제 래퍼 옵트인(v2.87) + /Alt 및 /ActualText 속성(v2.88) + 주석의 /StructParent + OBJR 역방향 연결(v2.89) + 페이지 콘텐츠의 BDC/EMC 자동 래핑(v2.90)을 포함합니다. 호출자는 여전히 구조 트리 토폴로지 결정(제목 계층 구조, 목록 중첩, 테이블 헤더)에 대한 책임을 가지지만, 기술적인 연결은 완전히 자동화되었습니다. 후보 #1 개발이 완료되었습니다.

2026-05-19 Version 2.89.0

  • PDF 1.7 §14.7.4.4에 따라 주석과 구조 간의 연결을 추가했습니다. 새로운 `THotPDF.RegisterAnnotForStructure(AnnotDict, StructElem)` 함수는 새로운 /ParentTree 키를 할당하고, 주석에 /StructParent를 추가하며, StructElem의 /ParentTree[Key]에 StructElem을 저장합니다 (주석의 경우 단일 참조 형식을 사용하며, 페이지 MCID 항목에서 사용하는 참조 배열 형식과 다릅니다). 또한, <</Type /OBJR /Obj <annotRef>>>를 StructElem의 /K 배열에 추가합니다. 이제 화면 읽기 프로그램은 모든 태그가 지정된 주석에서 시작하여 상위 구조 요소까지 이동할 수 있으며, 그 반대 방향으로도 이동할 수 있습니다.
  • `THPDFPage.AddURILink(Rect, URL): THPDFDictionaryObject` 기능이 추가되어, PDF/UA-1을 사용하는 사용자가 URI 주석을 생성할 수 있는 기능을 제공합니다. 기존의 `AddGoToLink`, `AddGoToRLink`, `AddLaunchLink` 메서드는 주석 딕셔너리를 반환하지 않았습니다 (이는 이전 API의 제한 사항입니다). 새로운 `AddURILink` 메서드는 간접 주석 딕셔너리를 반환하므로, 이를 `RegisterAnnotForStructure`에 직접 전달할 수 있습니다.
  • 사용자에게 보이는 영향: 이제 PDF/UA-1 규격에 적합한 문서에서 하이퍼링크를 세 줄의 코드를 사용하여 의미 구조와 함께 태그할 수 있습니다: `LinkAnnot := Doc.CurrentPage.AddURILink(R, 'https://example.org/'); LinkElem := Doc.AddStructureElement('Link', RootElem, -1, -1); Doc.RegisterAnnotForStructure(LinkAnnot, LinkElem);`. 문서 개요를 따르는 보조 기술은 이제 해당 링크에 접근하고, 링크의 목적을 알리고, 활성화 가능한 요소로 표시할 수 있습니다.
  • 구현 참고 사항: v2.11 버전에서 `/ParentTree` 및 `/Nums` 항목을 생성하는 `EmitTaggedPDFRoot` 루프는 `THPDFArrayObject(FParentTree.Items[I])`라는 강제 형 변환을 사용했습니다. v2.89 버전에서는 형 변환 범위를 `THPDFObject`로 확장했습니다. 그 이유는 주석 항목이 배열이 아닌 단일 딕셔너리를 저장하기 때문입니다. `THPDFArrayObject.AddObject`는 이미 런타임 `IsIndirect` 검사를 통해 처리하므로, 형 변환은 항상 형식적인 것이었습니다. v2.11 버전 이후에도 `FParentTree`에 저장된 배열의 바이트 안정성은 유지됩니다.
  • PDF 1.7의 14.7.4절에서는 `/ParentTree` 값이 배열(MCID로 인덱싱된 마크 콘텐츠 시퀀스의 경우) 또는 직접적인 `StructElem` 참조(주석, 비즈 및 기타 MCID가 아닌 구조 요소의 경우)일 수 있습니다. v2.89은 단일 참조 형식을 처음으로 사용하는 버전이며, 배열 형식은 v2.11의 `AddStructureElement-with-MCID` 경로를 통해 계속 작동합니다.
  • 후보 #1의 상태: PDF/UA 기능 구현의 세 번째 단계입니다. 아직 한 단계가 남아 있습니다. 페이지 콘텐츠의 BDC/EMC 자동 줄 바꿈 기능을 구현하여 `AddTextField` 및 `CurrentPage.TextOut` 함수를 통해 마크업된 콘텐츠 시퀀스를 수동 오퍼레이터 호출 없이 생성할 수 있도록 합니다. 그 후 PDF/UA 기능 구현이 만족스러운 수준에 도달할 것입니다.

2026-05-19 Version 2.88.0

  • `AddStructureElement` 함수에 선택적인 `/Alt` 및 `/ActualText` 속성 문자열을 허용하는 오버로드된 시그니처가 추가되었습니다. PDF/UA-1 (ISO 14289-1)에서는 텍스트가 아닌 콘텐츠(그림, 공식, 장식 글리프)에 대해 스크린 리더 친화적인 대체 텍스트를 제공해야 합니다. 새로운 오버로드 시그니처를 사용하면 이러한 대체 텍스트를 `StructElem`에 단일 호출로 쉽게 연결할 수 있습니다.
  • `/Alt` (대체 설명)은 보조 기술이 텍스트가 아닌 콘텐츠를 읽어줄 때 사용하는 내용이며, 일반적으로 이미지나 차트를 감싸는 요소 구조에 사용됩니다. `/ActualText`는 보이는 글자가 의도된 유니코드와 다를 때 복사-붙여넣기를 할 때 반환되는 내용이며, 일반적으로 장식적인 리가처, 드롭 캡, 추출하기 어려운 서체에 사용됩니다.
  • 두 속성은 표준 바이트 안전 SaveStringObject 이스케이프 경로를 통해 출력되는 PDF 텍스트 문자열입니다. 빈 문자열의 경우 해당 항목을 건너뛰므로 기존의 네 개의 인수를 사용하는 호출자는 동일한 바이트 출력을 유지합니다. 원래의 네 개의 인수를 사용하는 `AddStructureElement(Role, Parent, PageIndex, MCID)` 함수의 시그니처는 Pascal의 `overload` 지시어를 통해 유지됩니다.
  • 가시적인 효과: 이제 PDF/UA-1 준수 문서는 `AddStructureElement('Figure', Root, 0, 0, 'Company logo', '')`를 사용하여 로고 이미지를, `AddStructureElement('Span', Root, 0, 1, '', 'A bus stop')`를 사용하여 리가처(ligature) 영역을 표시할 수 있습니다. veraPDF 및 보조 기술은 추가 설정 없이도 생성된 `/Alt` 및 `/ActualText` 항목을 처리합니다.
  • 파이프라인 배치는 v2.88 버전에서 v2.11 기본 구현으로 전달되며 (따라서 StructTreeRoot 연결, /K 배열 추가, /Pg 백 링크, MCID/ParentTree 등록은 이전과 동일하게 수행됨) 이후에 두 개의 속성 항목만 추가됩니다. 기존 호출 위치는 변경되지 않으며, v2.74-v2.87 버전과의 바이트 안정성이 유지됩니다.
  • 후보 #1 상태: 이는 PDF/UA 프로듀서 측면의 추가 기능 개발의 두 번째 단계입니다. 후속 작업: 페이지 콘텐츠의 BDC/EMC 자동 줄 바꿈 (AddTextField + CurrentPage.TextOut 기능을 사용하여 수동 연산자 호출 없이도 마크된 콘텐츠 시퀀스를 생성할 수 있도록 함); 주석에 대한 /StructParents 연결 (스크린 리더 탐색이 링크/폼 위젯에도 도달할 수 있도록 함).

2026-05-19 Version 2.87.0

  • PDF/UA-1 (ISO 14289-1)의 고급 옵트인 기능을 새로운 `PDFUACompliance` 속성을 통해 추가했습니다. `BeginDoc` / `EndDoc` 전에 `True`로 설정하면, HotPDF가 호출자의 협력 없이도 충족할 수 있는 모든 PDF/UA-1 관련 요구 사항이 자동으로 활성화됩니다. 이러한 요구 사항에는 `/MarkInfo /Marked = true`, `/StructTreeRoot` 자리 표시자, `/Lang` (비어 있을 경우 기본값은 'en'), `/ViewerPreferences /DisplayDocTitle = true`, `/Metadata` XMP 스트림, 그리고 AIIM에 등록된 `pdfuaid:part = 1` 식별자가 XMP 패킷에 포함됩니다.
  • 이전에는 PDF/UA-1 준수를 위해 호출자가 EnableTaggedPDF, EnableXMPMetadata, Lang, ViewerPreferences (vpDisplayDocTitle) 및 Title을 개별적으로 설정하고 pdfuaid 네임스페이스를 추가하기 위한 사용자 정의 XMP 패킷을 만들어야 했습니다. v2.87에서는 이 모든 것을 PDFUACompliance:=True;로 통합했습니다. 개별 플래그는 여전히 사용 가능하며, 호출자가 명시적으로 설정하는 경우 존중됩니다.
  • XMP 패킷 업데이트: `BuildXMPPacket` 함수는 이제 `PDFUACompliance`가 True일 때 `xmlns:pdfuaid="http://www.aiim.org/pdfua/ns/id/"`와 함께 `1`를 출력합니다. veraPDF 및 기타 PDF/UA-1 검증기는 이 정확한 네임스페이스와 식별자 조합을 통해 문서를 PDF/UA-1 후보로 인식합니다.
  • 사용자에게 눈에 띄는 변경 사항은 다음과 같습니다. `Doc.Title := '...'; Doc.PDFUACompliance := True; Doc.BeginDoc; ...; Doc.EndDoc;`와 같이 작성된 PDF 파일은 추가적인 설정 없이 veraPDF에서 PDF/UA-1 준수 가능 대상으로 검증됩니다. 단, 문서 본문 작성자가 `AddStructureElement` 및 마크드 콘텐츠 시퀀스를 사용하여 실제 구조 트리를 작성해야 합니다. 정부, 교육 및 접근성 관련 출판 워크플로우에서 이제 하나의 스위치만 사용하면 됩니다.
  • 호출자 책임: PDF/UA-1 또한 구조 트리 무결성을 요구합니다 (모든 글리프가 태그가 지정된 구조 요소에 속해야 함). 그림/수식 콘텐츠에 대한 `/Alt` 또는 `/ActualText` 속성, 적절한 탭 순서, 유효한 제목 계층 구조 등이 필요합니다. 이 옵션은 기계 검사기가 먼저 확인하는 카탈로그/메타데이터 래퍼를 포함합니다. 완전한 의미적 준수는 호출자가 `AddStructureElement` 및 마크된 콘텐츠 BDC/EMC 연산자를 사용하여 구조 트리를 올바르게 구성하는 데 달려 있습니다.
  • 역호환성: PDFUACompliance의 기본값은 False이므로 v2.74부터 v2.86까지의 버전에서 호출하는 경우 바이트 단위로 동일한 출력을 유지합니다. 기존의 EnableTaggedPDF 및 EnableXMPMetadata 플래그는 새로운 옵션이 False일 때에도 이전과 동일하게 작동합니다.
  • 이것은 매트릭스 후보 #1의 첫 번째 부분입니다 (태그가 지정된 PDF / PDF/UA 제작 측면의 개선). 후속 업데이트 (v2.88+): `AddStructureElement`에서 `/Alt` 및 `/ActualText` 지원 추가, `AddTextField` 및 `CurrentPage.TextOut` 경로에 대한 페이지 콘텐츠 BDC / EMC 지원 추가, 그리고 주석에 대한 `/StructParents` 연결.

2026-05-19 Version 2.86.0

  • `RegisterUnicodeTTF`의 cmap 파서를 확장하여 OpenType 형식 12(전체 Unicode 범위를 세분화한 형식)을 처리할 수 있도록 했습니다. v2.75부터 v2.85까지는 형식 4(레거시 BMP 세그먼트 매핑)만 처리했지만, 이제 형식 12와 형식 4를 모두 포함하는 최신 글꼴은 더 풍부한 테이블을 사용합니다. 하위 테이블 선택 시 형식 12를 형식 4보다 우선하도록 설정했는데, 이는 형식 12가 전체 코드 포인트 범위에 대한 공식적인 정보이기 때문입니다.
  • 새로운 `_TTFParseCmapFormat12` 파서가 추가되었습니다. 이 파서는 16바이트 헤더(형식/예약/길이/언어/그룹 수)를 읽은 다음, `numGroups`개의 12바이트 그룹(시작 코드 포인트/종료 코드 포인트/시작 글리프 ID)을 반복합니다. 각 코드 포인트 C에 대해, 글리프 ID는 `startGlyphID + (C - startCharCode)`로 계산됩니다. 멀티바이트 읽기 작업 시 경계 검사를 수행하며, 잘리거나 형식이 잘못된 그룹은 오류 메시지 없이 건너니다.
  • 세부 테이블 점수 업데이트:
    • 플랫폼 3 (Microsoft) + 인코딩 10 (Unicode 전체) + 형식 12: 120 (최고)
    • 플랫폼 0 (Unicode) + 인코딩 4 또는 6 + 형식 12: 110
    • 다른 모든 형식 12: 105
    • 플랫폼 3 + 인코딩 1 (Unicode BMP) + 형식 4: 100 (레거시 BMP 대체)
    • 플랫폼 0 + 인코딩 3..4 + 형식 4: 80
    • 플랫폼 3 + 인코딩 10 + 형식 4: 70
    • 다른 모든 형식 4: 50
  • SMP 범위: CpToGid 출력 배열은 BMP 크기($10000개 항목 × 2바이트 = 128KB)를 유지합니다. 이는 Identity-H 인코딩이 2바이트 CID(0..65535)를 사용하기 때문입니다. 형식 12의 SMP 항목(U+10000 이상)은 파싱되지만 저장되지 않습니다. 형식 12의 처리 과정에서 endCharCode가 $FFFF로 잘린 후 반복됩니다. /CIDToGIDMap에서 SMP를 완전히 지원하려면 다른 인코딩(서로게이트 쌍 CMap 또는 Adobe-Japan1을 사용하는 Identity-V)이 필요하며, 이는 현재 범위에서 벗어납니다.
  • 눈에 띄는 개선 사항: 형식 12만 사용하는 글꼴(일부 최신 CJK 글꼴, Segoe UI Emoji/Symbol)의 경우, 이제 /W, /CIDToGIDMap, /FontFile2가 올바르게 채워지고 v2.84 서브세터가 적용됩니다. v2.86 이전 버전에서는 이러한 글꼴이 cmap 파싱의 자동 대체 기능을 사용하고 모든 스트림 출력을 건너뛰어 v2.74의 측정값만 사용했습니다.
  • 바이트 안정성: 형식 4인 글꼴(Arial, Tahoma)은 여전히 동일한 코드 경로를 거치며 동일한 CpToGid 출력을 생성합니다. 형식 4와 형식 12 모두인 글꼴은 이제 BMP의 경우 형식 12를 사용하며, 이는 일반적으로 동일한 BMP 매핑을 제공합니다(형식 12는 엄격한 상위 집합입니다). 기존 v2.74-v2.85 버전에서 이러한 글꼴에 대한 테스트는 여전히 바이트 안정성을 유지합니다.
  • 이 변경 사항은 v2.4.0부터 v2.86.0까지의 PDF 사양 준수 단계의 완료를 의미합니다. v2.86 이후의 나머지 작업(서로게이트 쌍 CMaps를 사용한 SMP 인코딩, 글꼴별 GSUB 스타일 대체, 더욱 발전된 서체)은 "기본 Type 0 / Identity-H + AcroForm Unicode" 범위에 포함되지 않으며, 실제 사용자 요구가 있을 때까지 무기한 연기됩니다.

2026-05-19 Version 2.85.0

2026-05-18 Version 2.84.0

  • EndDoc 시점에 작동하는 파일 기반 TrueType 서브세터를 추가했습니다. RegisterUnicodeTTF 및 AddTextField를 사용한 후, BuildUnicode*FieldContent 생성 과정에서 문서가 각 코드 포인트별 사용 정보를 누적합니다. EndDoc은 사용된 코드 포인트를 글리프 ID로 변환하고, 복합 글리프 구조를 탐색하며, 해당 글리프만 포함하는 임베디드 폰트 프로그램을 다시 생성합니다. v2.82 버전의 원본 임베딩을 대체했으며, 나머지 테이블 구조는 유효하게 유지됩니다. 왜냐하면 서브세터가 글리프 ID를 변경하지 않기 때문입니다 (glyf/loca 압축만 수행).
  • 사용자에게 직접적인 영향을 미치는 변경 사항은 다음과 같습니다. 내장된 Unicode TTF 글꼴이 포함된 PDF 파일의 크기가 크게 줄어듭니다. Arial 글꼴이 포함된 "Hello World" 문서는 v2.82 버전에서 약 350KB의 크기를 가졌지만, v2.84 버전에서는 약 10-15KB로 줄어듭니다. 일반적으로 1000-3000개의 글리프가 포함된 CJK 글꼴은 압축 후 약 14MB에서 500KB-2MB로 줄어듭니다.
  • 서브세터 알고리즘: 글리프 ID를 변경하지 않아 cmap, hmtx, /CIDToGIDMap, /W가 유효하게 유지됩니다. 각 글리프 인덱스 0부터 numGlyphs-1까지, 새로운 glyf 테이블은 원본 바이트를 복사하거나 (사용된 경우) loca[i+1] = loca[i]를 통해 빈 항목을 생성합니다 (사용되지 않은 경우). loca 형식 (head.indexToLocFormat에 따라 short 또는 long)은 유지됩니다. 각 테이블의 체크섬과 head.checksumAdjustment 값이 계산되어 TTF 사양에 따른 엄격한 유효성 검사를 수행합니다.
  • 복합 글리프 처리 개선: 사용된 글리프의 `numContours` 값이 -1인 경우(복합 글리프), 서브세터는 해당 글리프의 구성 요소 목록을 순회하며(각 구성 요소의 플래그, 글리프 인덱스 및 가변 인자/변환 건너뛰기를 파싱), 사용된 구성 요소를 표시하고 더 이상 새로운 글리프가 추가되지 않을 때까지 반복합니다. 경계 검사를 수행하여 잘못된 복합 글리프 체인이 무한 루프에 빠지지 않도록 합니다.
  • PDF 사양 준수: Type 0 딕셔너리의 /BaseFont, CIDFontType2 하위 글꼴, 그리고 FontDescriptor의 /FontName은 모두 사용된 글리프 집합의 결정론적 FNV-1a 해시에서 파생된 6자리의 "AAAAAA+" 서브셋 접두사를 갖습니다. 사양 9.6.4에 따라, 이 접두사는 글꼴 프로그램이 서브셋팅되었음을 나타냅니다. 그렇지 않으면 사양을 엄격하게 준수하는 리더는 포함된 글꼴 수정에 대해 경고합니다.
  • 사용량 추적 인프라: 65536개의 항목을 가진 FUnicodeUsedCps[] 부울 배열이 RegisterUnicodeTTF 함수가 처음 호출될 때 지연적으로 할당됩니다. 세 개의 BuildUnicode*FieldContent 도우미 함수(단일 행, 다중 행, 조합)는 UTF-16BE 16진수 Tj 연산자를 출력하면서 코드 유닛을 표시합니다. SetFormUnicodeFontDict('', nil) 함수와 향후 BeginDoc 호출은 상태를 초기화합니다.
  • 실패 시 안전 기능: 서브세터 단계가 완료되지 않는 경우(누락된 테이블, 잘못된 위치 정보, 복합 클로저 실패, 압축 실패 등), v2.82 버전의 원본 임베딩이 그대로 유지됩니다. PDF 파일 자체는 유효하게 유지되지만, 파일 크기만 증가합니다. 이를 통해 v2.82 버전의 안정성을 유지하면서, 정상적인 경우 서브세팅의 이점을 제공합니다.
  • 이 버전에서 포함되지 않은 내용은 다음과 같습니다. OpenType GSUB 아랍어/시리아어/데바나가리 문자의 문맥적 결합 기능, SMP cmap 형식 12 (여전히 BMP만 지원). 이 기능들은 v2.85 이상 버전에서 지원될 예정입니다.

2026-05-18 Version 2.83.0

  • RegisterUnicodeTTF에 PDF 1.7 ISO 32000-1 9.10.3 /ToUnicode CMap을 추가했습니다. 이제 Type 0 폰트 사전에는 Adobe-Identity-UCS CMap 스트림을 가리키는 /ToUnicode 간접 참조가 포함되어 있어, PDF에서 유니코드 텍스트를 추출할 수 있습니다. /ToUnicode가 없으면 v2.74-v2.82 버전의 PDF에서 복사-붙여넣기를 할 때 유니코드 코드 포인트 대신 원시 CID 인덱스가 생성되었으며, 화면 읽기 프로그램은 콘텐츠를 읽어낼 수 없었고, PDF/A 규격 준수에도 실패했습니다.
  • CMap 구조: 최소한의 Adobe-Identity-UCS CMap이며, 다음을 포함합니다: /CIDSystemInfo (Adobe / UCS / 0), /CMapName /Adobe-Identity-UCS, /CMapType 2, <0000>에서 <FFFF>까지의 단일 코드 공간 범위, 그리고 <0000>에서 <FFFF>까지를 <0000>에 매핑하는 단일 bfrange (identity). PostScript CMap 텍스트는 FlateDecode를 통해 약 150바이트로 압축되므로, 포함되는 오버헤드는 무시할 수 있습니다.
  • Identity 매핑의 근거: v2.74부터 v2.82까지의 설정에서는 Identity-H와 Adobe-Identity-0를 사용하며, CID는 Unicode 코드포인트와 동일합니다. 따라서 ToUnicode 역매핑은 BMP 전체에 걸쳐 진정으로 동일 매핑을 수행합니다. 단일 bfrange 항목으로 전체 매핑을 표현할 수 있으며, 각 코드포인트별 bfchar 목록이 필요하지 않습니다.
  • PDF 리더(Adobe, Foxit, Chrome PDF 뷰어)에서 텍스트 선택/복사-붙여넣기를 할 때, 이제 원래의 Unicode 코드 포인트가 출력되며, CID 쓰레기가 더 이상 나타나지 않습니다. 화면 읽기 프로그램(NVDA, JAWS, VoiceOver)은 접근성을 위해 AcroForm 텍스트 내용을 읽어줄 수 있습니다. PDF/A-1/2/3 표준 준수가 가능해졌습니다 (PDF/A는 모든 Type 0 글꼴에 대해 /ToUnicode를 요구합니다).
  • 파이프라인 배치는 `/ToUnicode` 생성이 `WArrayValid` try/except 블록의 외부에서 이루어집니다. 이는 아이덴티티 매핑이 cmap 파싱 성공 여부에 의존하지 않기 때문입니다. `/W`, `/CIDToGIDMap`, `/FontFile2`가 손상된 폰트 테이블로 인해 무시되더라도, `ToUnicode` CMap은 여전히 생성되며 의미적으로 올바릅니다.
  • 스트림 객체: 간접 THPDFStreamObject + /Filter /FlateDecode (ToUnicode는 텍스트 스트림이므로 /Length1이 없습니다). 결과 객체의 AddValue('ToUnicode', ...) 메서드를 통해 Type 0 래퍼 딕셔너리에 연결됩니다. v2.77의 /CIDToGIDMap 및 v2.82의 /FontFile2와 동일한 zlib 압축 패턴을 사용합니다.
  • 이 버전에서 포함되지 않은 내용은 다음과 같습니다. 각 코드 포인트에 대한 `bfchar` 항목(이를 통해 비-아이덴티티 CID를 `fi`와 같이 여러 문자 유니코드 시퀀스로 매핑할 수 있지만, 현재 아이덴티티 설정에서는 필요하지 않음); BMP 범위를 초과하는 SMP 지원(여전히 `0x0000..0xFFFF` 범위). 이 두 가지 기능은 v2.84+ 버전으로 연기되었습니다.

2026-05-18 Version 2.82.0

  • RegisterUnicodeTTF에 PDF 1.7 ISO 32000-1 9.6.4 + 9.9의 /FontFile2 원시 폰트 임베딩 기능을 추가했습니다. 실제 폰트 프로그램(이진 TTF/OTF 바이트)이 이제 PDF 내부에 /FontFile2 스트림으로 포함되어 폰트 설명자에 연결되므로, 사용자 측 리더는 더 이상 OS/애플리케이션 폰트 캐시를 통해 /BaseFont 이름을 확인해야 합니다. 결과적으로, 지정된 폰트가 없는 시스템에서도 올바르게 렌더링되는 독립적인 PDF 파일을 만들 수 있습니다.
  • 스트림 구조: `/Filter`가 `/FlateDecode`이고 `/Length1`이 압축되지 않은 폰트 파일 크기인 간접 `THPDFStreamObject`입니다 (사양 표 124 참조). 압축은 TZCompressionStream (zcDefault, windowBits 15)을 사용하며, 이는 v2.77의 `/CIDToGIDMap` 패턴을 따릅니다. 일반적인 라틴 폰트는 30-50% 정도 압축됩니다 (예: 700KB의 Arial이 350KB로 압축됨).
  • 파이프라인 통합: 배출은 v2.75의 `/W` 배열 및 v2.77의 `/CIDToGIDMap`과 동일한 WArrayValid 브랜치에서 발생합니다. 따라서 cmap 구문 분석에 실패할 경우(손상된 서브테이블/지원되지 않는 형식), 세 개의 기능 스트림이 모두 건너뛰어져 v2.74의 측정값만 사용하는 방식으로 정상적으로 이전 버전으로 되돌아갑니다.
  • 눈에 띄는 변경 사항: v2.74부터 v2.81까지의 PDF 파일은 기술적으로 Type 0 / CIDFontType2 복합 글꼴이었지만, 글꼴 프로그램이 누락되어 있었습니다. 사용자 뷰어는 `/BaseFont` (PostScript 이름)을 자체 글꼴 캐시에 매칭해야 했습니다. 정확히 동일한 이름의 글꼴이 설치된 시스템에서는 렌더링이 정상적으로 이루어졌지만, 그렇지 않은 시스템에서는 뷰어가 다른 글꼴로 대체하여 잘못된 글리프/메트릭을 표시하거나, 대신 빈 상자를 표시했습니다. v2.82에서는 PDF 파일 자체에 글꼴 프로그램을 포함했습니다. 이 글꼴 프로그램은 제작자가 `RegisterUnicodeTTF`에서 사용한 것과 동일합니다. 따라서 v2.82에서 뷰어의 렌더링은 운영 체제의 글꼴 가용 여부에 관계없이 일관되게 작동합니다.
  • 번역: 장점: 임베디드 글꼴을 사용하는 PDF 파일은 일반적인 라틴 글꼴의 경우 약 150KB에서 500KB, CJK 글꼴의 경우 2MB에서 20MB의 크기가 증가합니다(압축 크기 기준). 이는 소비자 측에서 글꼴을 대체하는 것과 동일한 문제이지만, 결정적이지 않은 렌더링을 초래합니다. 서브세팅(v2.83 이상)을 통해 사용하지 않는 글리프를 제거하여 파일 크기를 줄일 수 있습니다.
  • v2.82 버전에서 `/BaseFont`은 원래 PostScript 이름으로 유지됩니다 ( "AAAAAA+"와 같은 서브셋 접두사가 붙지 않음) 이유는 전체 글꼴을 포함하기 때문입니다. 사양 9.6.4에 따르면 6자 접두사는 글꼴 프로그램이 서브셋 처리되었을 때만 적용되며, v2.83 버전부터는 서브세터 통합의 일환으로 이 접두사가 추가될 예정입니다.
  • 이 버전에서 포함되지 않은 내용은 다음과 같습니다: 글꼴 서브세팅 (따라서 단일 임베디드 글꼴은 PDF 파일 전체 크기에 영향을 줍니다). ToUnicode CMap (PDF/A 복사-붙여넣기에 사용). SMP cmap 형식 12 (U+10000 이상의 코드 포인트는 아직 매핑되지 않음). 이 모든 내용은 v2.83 이상 버전에서 처리됩니다.

2026-05-18 Version 2.81.0

  • UAX #9 W4 (数字之间的分隔符) 和 W5 (紧邻数字的终止符) 已被应用到从左到右 (LTR) 段落重排路径。此前,仅支持从右到左 (RTL) (自 v2.72.0 / v2.73.0 起); v2.81 将这两个处理过程提取到共享的 `_ApplyUAX9W4Rules` 和 `_ApplyUAX9W5Rules` 辅助函数中,以便两个段落方向都应用相同的弱规则转换。
  • 리팩터링: RTL 경로의 1단계 b (W4) 및 1단계 c (W5)에 있던 인라인 코드를 단일 라인 헬퍼 함수 호출로 대체했습니다. 이러한 헬퍼 함수는 와이드 문자열과 Classes[] 배열을 입력으로 받아 Classes[] 배열을 직접 수정하며, 로직은 v2.72/v2.73 버전의 인라인 구현과 동일하므로, 리팩터링 과정에서 RTL 출력의 바이트 안정성이 유지됩니다.
  • LTR 경로에 Step 1c (W4) 및 Step 1c.2 (W5)가 추가되어 W1 NSM 상속 (Step 1b)과 W7 EN-preceded-by-L (Step 1d) 사이에 위치합니다. 이후 N 규칙 (Step 1e) 및 I 규칙 (Step 1f)은 파이프라인 순서를 명확하게 하기 위해 재정렬되었습니다.
  • 눈에 보이는 왼쪽에서 오른쪽(LTR) 방향에 미치는 영향: 혼합된 LTR 환경에서, RTL(오른쪽에서 왼쪽) 스타일의 문자가 숫자/ET(Entity) 표현식 앞에 올 때, W5는 N1이 이를 R(Run) 그룹으로 묶기 전에 ET를 EN(English)으로 변경합니다. 예시: "Hi shin $1" (LTR 단락 내부에 히브리어 문자 "shin"이 포함된 문자열, 그 뒤에 "$1"이 오는 경우), 이전에 "Hi $ shin 1"으로 출력되었으며, "$"가 R 그룹으로 이동하여 "shin"과 교체되었습니다. v2.81에서는 "Hi shin $1"로 출력되며, "$"가 숫자와 붙어 있습니다. 동일한 원리가 W4에도 적용됩니다. "Hi shin $1,2 widgets"에서 "$1,2"는 쉼표를 기준으로 분리되지 않고 논리적인 덩어리로 유지됩니다.
  • LTR 경로에서 바이트 안정성을 유지하는 경우: "12,345 widgets"와 같이 R이 앞에 없는 순수한 LTR 입력은 W7 sor=L이 모든 EN을 L로 처리하기 때문에 눈에 띄는 변화가 없습니다. 숫자나 ET가 없는 L + RTL만 포함하는 LTR 입력도 영향을 받지 않습니다. 기존 v2.79 LTR 테스트(smoke_bidi_n_rules_ltr, smoke_bidi_ltr_reorder)는 여전히 바이트 단위로 동일하게 통과합니다.
  • 파이프라인 순서 (RTL 경로 변경 없음): W1 -> W4 -> W5 -> W7 -> N0 -> N1 -> N2 -> I2 -> L2. LTR 경로는 이제: W1 -> W4 -> W5 -> W7 -> N0 -> N1 -> N2 -> I 규칙 -> L2. 두 경로는 W4/W5/W7/N 규칙 도우미를 공유하며, RTL과 LTR 간의 유일한 차이점은 분류(1단계)와 최종 L2 처리 과정입니다.
  • UAX #9 관련 작업이 아직 완료되지 않았습니다. OpenType GSUB의 아랍어/시리아어/데바나가리 문자 결합 기능 구현 및 RegisterUnicodeTTF 관련 작업(ToUnicode CMap, SMP cmap 형식 12, /FontFile2 및 서브세팅)이 남아 있습니다.

2026-05-18 Version 2.80.0

  • 유니코드 UAX #9 W7 유럽 숫자 연결 기능이 추가되었습니다. 스캔 결과 강력한 L(또는 sor=L)이 발견되면 해당 문자는 L로 변환됩니다. 이 변환은 양방향(RTL) 및 단방향(LTR) 문단 경로 모두에서 W4(숫자 사이 구분자) 및 W5(숫자 바로 뒤에 오는 종료 문자) 이후에 실행됩니다. 따라서 W4에 의해 EN(European Number)으로 승격된 모든 구분자는 L-연결 기능의 영향을 받습니다.
  • 눈에 띄는 RTL(오른쪽에서 왼쪽) 영향: 이전에 ""Hello 123 Arabic""과 같은 입력이 RTL 단락에서 시각적으로 ""Arabic SP 123 SP Hello""로 표시되었는데, 이는 EN(영문) 텍스트가 L(Hello)과 AL(Arabic) 사이에 위치하여 N(숫자) 규칙이 LTR(왼쪽에서 오른쪽) 구문을 두 개의 독립적인 텍스트 블록으로 분리했기 때문입니다. v2.80 W7에서는 EN 텍스트를 L로 변환합니다(L이 앞에 오기 때문). 또한 N1은 Hello와 123 사이의 선행 공백을 L 텍스트 블록에 통합합니다. 결과적으로 "Hello 123" 전체가 하나의 레벨 2 서브 문자열로 처리되어 단위로 반전됩니다. 최종 시각적 레이아웃은 ""Arabic SP Hello SP 123""이 되며, 이는 UAX #9의 엄격한 동작과 일치합니다.
  • W7이 작동하지 않는 경우는 다음과 같습니다. EN 앞에 가장 가까운 강한 문자(strong)가 R 또는 AL(아랍 문자)인 경우, EN이 RTL 문단에서 버퍼의 시작 부분에 있는 경우(sor=R), 또는 EN 앞에 L이 전혀 없는 경우입니다. 이러한 경우, v2.80 이전의 동작이 유지됩니다. v2.72/v2.73 버전의 W4/W5 기준선 관련 문제는 이전과 동일하게 바이트 안정성을 유지합니다.
  • LTR 단락 효과: W7은 사양 일관성을 위해 LTR 경로에서도 실행됩니다. 스캔이 버퍼 시작에 도달하면 sor=L로 설정됩니다. HotPDF의 단순화된 단일 임베딩 LTR I 규칙에서, L과 EN은 모두 레벨 0에 위치하므로 EN에서 L로의 변환은 Levels[] 배열을 직접 변경하지 않습니다. 하지만 N1 흡수 패턴은 변경됩니다. L과 L-브리지된 EN 사이에 SP가 있으면 N1의 동일 방향 조건을 만족하며, 이 SP는 런에 포함됩니다. 순수한 LTR 입력에서 내부 RTL이 없는 경우, 변경 사항은 바이트 안정적인 무효 작업입니다. LTR 입력에 후행 RTL이 포함된 경우 (예: "Hello 123 shalom"), SP의 위치는 RTL 블록에 대해 한 위치만큼 이동합니다.
  • W6 (잔여 ES/CS/ET -> ON, 엄격한 UAX #9에 따름)은 HotPDF의 간소화된 Classes[] 테이블에 명시되어 있습니다. ES, CS, ET, WS, ON은 모두 클래스 0 (bcOther)을 공유하며, N 규칙은 클래스 0을 동일하게 처리합니다. 우리의 모델에서 W6을 ON으로 승격시키는 것은 N1/N2이 ON과 WS를 구별하지 않기 때문에 아무런 영향도 미치지 않습니다. 관련 내용은 코드 주석에 자세히 설명되어 있습니다.
  • 파이프라인 순서 (오른쪽에서 왼쪽 방향): W1 NSM 상속 -> W4 숫자 사이의 ES/CS -> W5 숫자에 인접한 ET -> W7 L 다음에 오는 EN -> N0 쌍 대괄호 -> N1 동일 방향의 NI 흡수 -> N2 기본 임베딩 -> I2 레벨 할당 -> L2 역방향. 왼쪽에서 오른쪽 방향에서도 동일한 순서를 따르지만 W4/W5는 제외됩니다 (이 부분은 오른쪽에서 왼쪽 방향에서만 사용되며, 왼쪽에서 오른쪽 방향으로의 W4/W5 기능은 다음 개발 대상입니다).
  • 새로운 공유 `_ApplyUAX9W7Rules(Classes, ParaIsRTL)` 보조 절차는 Classes[] 배열을 직접 수정합니다. 스캔 과정에서 약한 위치, NSM 위치, EN 위치, AN 위치는 건너빰니다. L, R, AL 위치만 강한 유형으로 간주됩니다. 스캔이 강한 유형을 찾지 못하면 단락 방향(sor)이 암시적 강한 유형으로 사용됩니다. RTL 경로는 ParaIsRTL=True를 전달하고, LTR 경로는 False를 전달합니다.
  • UAX #9 관련 작업은 아직 완료되지 않았으며, 다음 작업들이 남아 있습니다: LTR 경로 W4/W5 지원 (현재는 RTL만 지원), OpenType GSUB 아랍어/시리아어/데바나가리 문자 결합 기능, 그리고 RegisterUnicodeTTF 관련 작업 (ToUnicode CMap, SMP cmap 형식 12, /FontFile2 및 서브세팅).

2026-05-18 Version 2.79.0

  • v2.78.0의 N0/N1/N2 규칙을 LTR 단락 재정렬 경로에 반영했습니다. 다중 단어 RTL 구가 LTR 단락 내에 포함될 때 발생하는 대칭 오류를 수정합니다 (예: 여러 히브리어 또는 아랍어 단어가 공백으로 구분되어 포함된 영어 문장). 이 경우, 단어 간 공백이 레벨 0에 머물러 RTL 구가 독립적인 R 실행 단위로 분리되어 시각적으로 단어가 뒤바뀌어 보였습니다. v2.79 N1에서는 공백이 주변 R 실행 단위에 흡수되어, 전체 구가 레벨 1의 서브 문자열이 되고, L2 역순 처리로 인해 단어가 논리적인 순서대로 유지됩니다.
  • LTR 문단 처리 로직(`_ApplyUAX9L2ReversalLTRPara`)을 리팩터링하여 RTL 처리 로직과 동일한 구조를 갖도록 변경했습니다. 각 UTF-16 코드 유닛을 `Classes[]` 바이트 배열로 분류하고, `Classes[]`에 대해 W1 NSM 상속을 적용합니다 (v2.79 이전에는 `Levels[]`를 사용했습니다). 그런 다음, 임베딩 방향 매개변수(LTR의 경우 1, RTL의 경우 2)를 사용하여 `Classes[]`에 대한 공통 `_ApplyUAX9NRules` 헬퍼 함수를 호출합니다. I 규칙은 `Classes[]`로부터 `Levels[]`를 파생시킵니다. 이제 RTL 및 LTR 처리 로직 모두 동일한 N 규칙 구현을 공유합니다.
  • `_ApplyUAX9NRules(Wide, Classes, EmbedDirCls)` 함수는 임베딩 방향을 클래스 값(1 또는 2)으로 받아 N0 쌍 대괄호 해소, N1 동일 방향 NI 흡수, N2 균일한 기본값-임베딩을 적용합니다. 오른쪽에서 왼쪽(RTL) 방향은 2(R)를, 왼쪽에서 오른쪽(LTR) 방향은 1(L)를 사용합니다. 모든 v2.78 버전의 오른쪽에서 왼쪽(RTL) 동작은 바이트 단위로 그대로 유지됩니다.
  • 눈에 띄는 좌측(LTR) 영향: "Hi shalom olam World"라는 텍스트가 이전에 두 개의 히브리어 단어가 서로 반전된 상태로 표시되었는데 (각 단어 자체는 올바르지만, 상대적인 위치가 바뀜). v2.79는 논리적인 단어 순서를 유지하므로, 오른쪽에서 왼쪽(RTL)로 읽는 사용자는 "Hi shalom olam World"라는 텍스트를 히브리어 부분이 예상되는 순서대로 볼 수 있습니다. 동일한 수정 사항이 N0 및 N1의 협력을 통해 괄호로 묶인 다중 단어 RTL 구문에 적용됩니다.
  • LTR 경로의 파이프라인 순서는 다음과 같습니다 (RTL 경로를 반영). 분류는 Classes[]로 시작하여 W1 NSM 상속, N0 쌍괄호 처리, N1 동일 방향 NI 흡수, N2 기본 임베딩, I 규칙 (Levels[] 파생), L2 레벨 1 런 역순으로 진행됩니다. W4/W5 숫자 처리 단계는 아직 LTR 경로로 이식되지 않았습니다. 숫자와 구분 기호 조합이 있는 LTR 단락은 N 규칙을 통해 변경 없이 처리됩니다.
  • 기존의 왼쪽에서 오른쪽(LTR) 테스트에서 바이트 안정성이 유지됩니다. 순수한 LTR ASCII 텍스트, LTR 단락 내의 단일 단어 오른쪽에서 왼쪽(RTL) 텍스트, 그리고 RTL과 LTR이 혼합되어 있지만 RTL 단어 사이에 공백이 없는 경우에도, 리팩터링 후 동일한 Levels[] 배열이 생성됩니다 (W1 NSM 상속 단계는 Levels[] 또는 Classes[]에 적용하든 결과가 동일합니다). v2.67, v2.69 및 v2.71 버전의 LTR 테스트는 여전히 바이트 단위로 동일한 결과를 보여줍니다.
  • 다음 작업이 아직 남아 있습니다: W6/W7 관련 미세 조정, LTR 경로에서 W4/W5의 숫자 처리 (현재는 RTL만 지원), OpenType GSUB에서 아랍어/시리아어/데바나가리 문맥 기반 결합, 그리고 RegisterUnicodeTTF 관련 작업 (ToUnicode CMap, SMP cmap 형식 12, /FontFile2 및 서브세팅).

2026-05-18 Version 2.78.0

  • RTL 단락 재정렬 파이프라인에 Unicode UAX #9의 간소화된 N0 쌍괄호 해결, N1 중립-동일-강력 흡수, N2 중립-기본-임베딩 규칙을 추가했습니다. 다단어 LTR 구가 RTL 단락 내에 포함될 때 발생하는 문제를 해결합니다 (예: 히브리어 또는 아랍어 텍스트로 영어 텍스트를 감싸고 내부 공백이 있는 경우). 기존 방식에서는 L 런 사이의 공백이 임베딩 레벨에 남아 LTR 구가 독립적인 하위 런으로 분리되어 단어가 역순으로 출력되었습니다. N1을 사용하면 공백이 주변 L 런에 흡수되어 전체 구가 레벨 2의 하위 문자열이 되고, L2 역-역전 기능을 통해 논리적인 순서가 유지됩니다.
  • N0 브래킷: 22개의 BMP 브래킷 쌍을 처리하며, ASCII 괄호/대괄호/중괄호부터 수학/타이포그래피 기호(천장, 바닥, 수학 각도, 수학 흰색 사각형, 흰색 중괄호) 및 CJK 구두점 브래킷(각도, 이중 각도, 모서리, 흰색 모서리, 검은색 렌즈 모양, 거북이 등껍질, 흰색 거북이, 흰색 사각형) 및 전체 폭 형태까지 지원합니다. BD16 스택 기반 쌍 브래킷 감지 기능을 사용하며, 사양에 따라 최대 63개의 항목을 처리할 수 있습니다. 쌍 브래킷 해상도는 내부에서 가장 강력한 방향(L, R, AL, EN, AN)을 찾으며, 여기서 EN/AN은 사양에 따라 R으로 간주됩니다. 내부 방향이 포함 방향과 다른 경우, 브래킷을 열기 전에 방향을 확인하는 기능을 제공합니다.
  • N1 흡수: `Classes[]`를 사용하여 `bcOther` (중립)의 최대 연속 블록을 찾고, 왼쪽과 오른쪽의 NSM이 아닌 강력한 유형을 찾습니다. 또한 양쪽이 동일한 방향의 영향을 받는 경우 (둘 다 L이거나, 둘 다 R과 동일하게 EN/AN을 R로 계산), 전체 블록이 해당 방향을 따릅니다. 실제 영향: 아랍어/히브리어 단락 내에 포함된 영어 구절 내의 공백/쉼표/마침표/콜론이 더 이상 분리되지 않고 구절과 함께 그룹화됩니다.
  • N2 기본 설정: 나머지 `bcOther` 위치(강조 기호가 없거나, 왼쪽/오른쪽 강조 기호가 일치하지 않는 경우)는 임베딩 방향을 따릅니다. RTL 문단에서는 이 방향이 오른쪽(R)입니다. 클래스 2에 해당합니다. N2 이후, `Classes[]` 배열의 모든 항목은 해결된 집합 {1..6}에 포함되므로, I2 레벨 할당은 더 이상 `bcOther`가 기본적으로 레벨 1로 설정되는 것에 의존하지 않습니다.
  • 눈에 띄는 변경 사항: 이전에 HotPDF는 "aleph aleph SP a b c SP d e f SP aleph aleph" (영어로 "abc def"라는 문구가 포함된 RTL 단락)을 "aleph aleph SP d e f SP a b c SP aleph aleph"로 출력했는데, 단어 순서가 바뀌었습니다. 이는 단어 간의 공백이 레벨 1(RTL 임베딩)에 있기 때문입니다. v2.78에서는 "aleph aleph SP a b c SP d e f SP aleph aleph"로 출력되어 문구가 올바르게 유지됩니다. 이제 임베딩된 문구 주위에 있는 괄호가 소비자 측에서 N0 + L4 미러링을 통해 올바르게 처리됩니다.
  • 파이프라인 순서: W1 NSM 상속 -> W2/I2 (BIDI 테이블에서 EN/AN 클래스 할당, 이 단계에서는 수행되지 않음) -> W4 숫자 사이의 ES/CS -> W5 숫자에 인접한 ET -> N0 쌍 대괄호 -> N1 동일 방향 흡수 -> N2 임베딩 기본값 -> I2 레벨 할당 -> L2 역-역. N 규칙은 W와 I 사이에 위치하며, 기존 W 규칙의 출력은 N 규칙의 입력으로 사용됩니다.
  • 기존 스모크에서 다중 단어의 왼쪽-오른쪽(LTR) 문구가 포함되지 않은 경우, 바이트 수준에서 안정적입니다. 이는 순수 오른쪽-왼쪽(RTL), 순수 LTR(함수는 입력을 반환), RTL 내의 단일 단어 LTR(내부 중립 문자가 없어 흡수되지 않음), 아랍어 + 서식 있는 숫자 + 쉼표(공백은 bcOther에서 R-호환으로 전환되지만 동일한 수준에서 유지되므로 L2 역방향 출력이 변경되지 않음)을 포함합니다. v2.66, v2.67, v2.68, v2.71, v2.72, v2.73 버전의 기본 스모크는 여전히 바이트 단위로 동일하게 작동합니다.
  • UAX #9 관련 작업은 아직 완료되지 않았으며, 다음과 같은 작업이 남아 있습니다: W6/W7 관련 미세 조정, N 규칙에 따른 LTR 문단 미러링 (LTR 문단 내에 포함된 다중 단어 RTL 구문), OpenType GSUB 아랍어/시리아어/데바나가리 문맥 기반 결합, 그리고 RegisterUnicodeTTF 관련 작업 (ToUnicode CMap, SMP cmap 형식 12, /FontFile2 및 서브세팅).

2026-05-18 Version 2.77.0

  • THotPDF의 Type 0 / CIDFontType2 + Identity-H 설정에서, RegisterUnicodeTTF에 PDF 1.7 ISO 32000-1 9.7.4.2 /CIDToGIDMap 스트림을 추가했습니다. 이제 BMP 내의 각 Unicode 코드 포인트(CID)는 임베디드 글꼴 프로그램 내의 실제 글리프 인덱스로 매핑됩니다. v2.77 이전에는 /CIDToGIDMap 항목이 지정되지 않았으며, 이는 사양에 따라 기본적으로 /Identity로 설정됩니다. 이로 인해 뷰어 프로그램은 글꼴의 글리프 테이블을 CID로 직접 인덱싱하여 거의 모든 문자에 대해 잘못된 글리프를 표시했습니다. 이는 실제 글꼴 글리프 테이블에서 글리프 인덱스 N이 Unicode 코드 포인트 N과 일치하는 경우가 드물기 때문입니다.
  • 이 구현은 v2.75의 /W 배열에 대해 이미 수행된 cmap 파싱을 재사용합니다. CpToGid[0..$FFFF] 메모리 테이블은 131072바이트 스트림으로 직렬화되며(각 CID당 2바이트, 빅 엔디안), FlateDecode로 압축됩니다. 일반적인 실제 글꼴의 압축률은 80-95%입니다. 이는 대부분의 BMP 코드 포인트에 해당하는 글리프가 없기 때문에 0x0000으로 직렬화되기 때문입니다. 압축된 스트림은 CIDFontType2 하위 딕셔너리에 간접 /CIDToGIDMap 항목으로 연결됩니다.
  • 눈에 띄는 개선 사항: `RegisterUnicodeTTF`와 `SetFormUnicodeFontDict`를 사용하여 생성된 PDF에서, `AcroForm` 텍스트 필드 위젯이 이제 원본 글꼴이 직접 렌더링하는 것과 동일한 글리프를 최종 사용자 리더에서 표시합니다. v2.77 이전 버전의 PDF에서 `/Identity` 기본 설정을 사용하는 경우, 규격 준수를 중요시하는 리더에서 눈에 띄게 잘못된 렌더링이 발생했습니다 (의도한 라틴 문자/숫자/구두점 문자의 위치에 임의의 글리프가 표시됨). 일부 리더는 Unicode를 사용하여 cmap을 해석하는 방식으로 작동하여 올바르게 렌더링했지만, 이는 표준이 아닌 동작이었습니다.
  • 파이프라인 배치: `/CIDToGIDMap` 생성이 `/W`를 생성하는 동일한 `WArrayValid` 분기 내에서 이루어지므로, 두 항목은 cmap 탐색을 공유하며, 두 번째 압축 단계만 새로 추가됩니다. cmap, hmtx, maxp 파싱에 실패하면, 오류를 숨기는 방식으로 `/W`와 `/CIDToGIDMap` 모두 건너뛰고, 소비자 리더는 v2.77 이전 버전의 딕셔너리를 보고 기본 cmap 해석을 사용합니다.
  • 이 버전에서 지원하지 않는 기능 (v2.78 이상에서 구현 예정): SMP cmap 형식 12 (U+10000 이상의 코드 포인트는 여전히 테이블에서 GID 0에 매핑됨), /FontFile2 스트림 임베딩 (따라서 읽는 프로그램은 자체 글꼴 매칭을 통해 /BaseFont 이름을 확인함), 글꼴 서브세팅 (128KB의 원본 맵은 전체 범위를 포함함), 그리고 복사-붙여넣기 및 접근성 기능을 위한 ToUnicode CMap.

2026-05-18 Version 2.76.0

  • v2.75.0 버전의 TTF 글꼴의 /W 어드밴스 폭 배열을 HotPDF의 자체 멀티라인 단어 래핑 알고리즘에 통합했습니다. v2.65.0 버전의 BuildUnicodeMultilineFieldContent.CodeUnitAdvance 도우미는 이제 RegisterUnicodeTTF에 의해 채워진 각 코드 포인트별 어드밴스 캐시를 참조하며, 이전의 0.5/1.0이라는 좁은/넓은 비율 추정치를 실제 글리프 메트릭으로 대체합니다. 생성 측면에서의 줄 바꿈은 이제 소비자 측면의 /W 렌더링과 일치합니다. HotPDF가 선택하는 래핑 지점은 소비자 리더가 실제로 /Tj 연산자를 그릴 때 줄 바꿈을 수행하는 위치와 일치합니다.
  • 새로운 비공개 필드: `FAcroFormUnicodeAdvances` (크기가 65536이거나 비어 있는 단어 배열)는 PDF 디자인 단위(em당 1000)로 각 코드 포인트의 전진 폭을 캐싱합니다. `FAcroFormUnicodeAdvancesActive` 플래그는 "RegisterUnicodeTTF에 의해 채워진 캐시"와 "글꼴이 로드되지 않은 경우(휴리스틱이 기본값으로 사용)"를 구별합니다. `RegisterUnicodeTTF`는 `/W` 배열을 생성하는 것과 동일한 hmtx + cmap 순회 과정에서 이러한 필드를 채우므로 추가 파싱 과정이 필요하지 않습니다.
  • CodeUnitAdvance 조회 순서: 만약 `FAcroFormUnicodeAdvancesActive`가 활성화되어 있고 캐시에 해당 코드 유닛에 대한 0이 아닌 값이 있다면, 스케일된 너비를 1000.0으로 나누고 em 단위 값으로 반환합니다. 그렇지 않으면 v2.65의 휴리스틱을 사용합니다 (ASCII/Latin-1은 좁게, CJK/Hangul/Hiragana/Katakana/전체 너비는 넓게). 서로게이트 쌍의 절반은 여전히 휴리스틱을 통해 처리됩니다. 왜냐하면 캐시는 BMP(Basic Multilingual Plane)만 지원하기 때문입니다.
  • 캐시 수명: `THotPDF.Create` 호출 시 (기본적으로 비어 있거나 비활성 상태), 호출자가 명시적으로 Unicode 글꼴 등록을 재설정할 때 `SetFormUnicodeFontDict('','')` 호출 시, 그리고 이후의 각 `RegisterUnicodeTTF` 호출 시 다시 채워집니다. 128KB (64K 코드 포인트 * 2 바이트)의 공간을 사용하며, 이는 최소 하나의 TTF 파일이 로드되었을 때만 해당됩니다. Unicode 글꼴을 전혀 사용하지 않는 경우에는 메모리 사용량이 0입니다.
  • RegisterUnicodeFontDict (v2.70.0) 및 RegisterUnicodeTTF (v2.74.0) 함수가 `/W` 배열 없이 호출될 경우 (예: `maxp`, `cmap`, `hmtx` 테이블이 누락된 경우), 캐시가 비워지거나 비활성화됩니다. 따라서 다중 행 텍스트 줄 바꿈은 v2.65 버전의 휴리스틱을 사용하며, 해당 경우 v2.65 버전과 동일한 결과를 출력합니다.
  • 눈에 띄는 개선 사항: 여러 줄의 AcroForm 텍스트 위젯에서, 일반적인 라틴 문자(Arial, Segoe UI, Times)를 사용하는 경우, 이제 텍스트가 실제 리더 프로그램의 레이아웃과 일치하는 문자 경계에서 줄 바꿈됩니다. v2.76 이전 버전에서는 v2.65의 규칙에 따라 모든 ASCII 문자를 0.5em 너비로 처리했습니다. 그러나 실제 글꼴에서 "M"은 약 0.8em이고 "i"는 약 0.3em이므로, 이 규칙은 30~60% 정도 과대 또는 과소 추정하여, HotPDF에서 의도한 것과 다른 방식으로 줄 바꿈이 이루어지게 됩니다. 이는 텍스트가 넘치거나 줄이 너무 짧아지는 문제를 일으킵니다.
  • `BuildUnicodeTextFieldContent` 및 `BuildUnicodeCombFieldContent` 함수는 `CodeUnitAdvance`를 사용하지 않으며, 변경 사항이 없습니다 (단일 행은 줄 바꿈이 없고, 조합 문자는 동일 너비 셀을 사용합니다).
  • 이 버전에는 다음 내용이 포함되지 않습니다: SMP cmap 형식 12 (U+10000 이상의 코드 포인트는 여전히 서브로게이트 절반에 대한 휴리스틱을 통해 처리됨), ToUnicode CMap, /FontFile2 스트림 임베딩, 글꼴 서브세팅. 이러한 기능은 v2.77 이상 버전에서 제공됩니다.

2026-05-18 Version 2.75.0

  • v2.74.0 버전의 THotPDF에서 `RegisterUnicodeTTF` 기능을 개선하여 hmtx, maxp 및 cmap 정보를 파싱하고, 결과적으로 생성되는 CIDFontType2 폰트가 각 코드 포인트에 대한 실제 너비 정보를 포함하도록 했습니다. 이제 렌더링 시, 소비자 리더는 텍스트 너비 계산에 실제 폰트 메트릭을 사용하며, 이전에는 모든 글리프에 대해 `/DW = 1000`을 사용하는 대신, AcroForm의 `/AP` appearance 스트림 내 텍스트가 원본 폰트가 렌더링할 때와 동일한 너비를 갖도록 했습니다.
  • 새로운 단위 수준의 도우미 함수는 세 개의 추가 SFNT 테이블을 파싱합니다: `_TTFParseMaxpNumGlyphs` (maxp에서 numGlyphs를 읽음), `_TTFParseHmtxAdvances` (hmtx에서 각 글리프의 전진 폭 배열을 읽고, hhea의 numberOfHMetrics 값에 따라 크기를 결정), `_TTFFindAndParseCmap + _TTFParseCmapFormat4` (BMP 세그먼트 매핑 형식 4 서브테이블을 통해 유니코드 코드포인트를 글리프 ID로 매핑). `_TTFBuildWArray` 함수는 PDF 1.7 9.7.4.3의 형식 1인 희소 /W 배열을 구성합니다. 이 함수는 연속된 기본값이 아닌 폭을 가진 코드포인트를 `[startCID [w1 w2 w3 ...]]` 형식의 그룹으로 묶고, 폭이 `/DW = 1000`인 코드포인트는 배열 크기를 줄이기 위해 건너니다.
  • Cmap 서브테이블 선택 시, Microsoft Unicode BMP (플랫폼 3, 인코딩 1, 형식 4)를 우선적으로 사용합니다. 이는 Windows 운영체제에서 널리 사용되는 글꼴 cmap 레이아웃입니다. 크로스 플랫폼 OpenType 글꼴의 경우, Unicode 플랫폼 (0, 인코딩 3 또는 4)를 사용하고, 그 다음에는 플랫폼 3, 인코딩 10 (Unicode 전체, 형식 4만 해당)을 사용하며, 마지막으로 다른 형식 4를 사용합니다. 형식 4가 아닌 서브테이블 (형식 0, 2, 6, 8, 12, 13, 14)은 이 부분에서 무시되며, 형식 12를 사용한 SMP 지원은 v2.76+ 버전부터 적용됩니다.
  • `/W` 배열은 직접 탐색을 통해 `CIDFontType2` 하위 딕셔너리에 연결됩니다: `Type0` -> `/DescendantFonts` -> `[0]` -> `AddValue('W', WArray).` `v2.70`에서 `RegisterUnicodeFontDict` 함수의 시그니처는 변경되지 않았으며, 하위 딕셔너리는 조립 후에 직접 수정됩니다.
  • hmtx에서 가져온 FUnit 너비는 head 테이블의 unitsPerEm 값을 사용하여 PDF 디자인 단위(em당 1000)로 조정됩니다. 매핑된 글리프가 없는 코드 포인트(cmap이 0 또는 .notdef을 반환하는 경우)는 DW = 1000으로 처리되고 /W에서 제외됩니다. 일반적인 라틴 문자 글꼴(Arial, Segoe UI, Times)의 경우, 결과적으로 생성되는 /W에는 500-1500개의 코드 포인트 항목이 포함됩니다. CJK 글꼴의 경우, 배열의 크기는 10,000개 이상의 항목으로 늘어날 수 있습니다.
  • 이 버전에서 구현되지 않은 기능은 다음과 같습니다 (v2.76 이상에서 구현 예정): HotPDF 자체의 다중 행 텍스트 줄 바꿈 알고리즘에서 `/W` 너비 데이터가 아직 사용되지 않습니다. v2.65 버전의 `BuildUnicodeMultilineFieldContent`는 여전히 줄 바꿈 계산을 위해 0.5/1.0의 좁은/넓은 비율을 사용합니다. `/W` 배열은 렌더링 정확도를 높이기 위한 것입니다. 완벽한 줄 바꿈 기능 (`/W`를 사용하여 줄 바꿈 계산)은 v2.76 이상에서 구현됩니다. 또한 다음과 같은 기능은 아직 구현되지 않았습니다: cmap 역 매핑을 사용한 ToUnicode CMap, `/FontFile2` 스트림 임베딩, 글꼴 서브세팅, 그리고 SMP cmap 형식 12.
  • `/W` 파싱 과정에서 예외 처리 기능이 추가되었습니다. 만약 `maxp`, `cmap`, `hmtx` 정보가 누락되었거나, 하위 테이블이 손상된 경우, `RegisterUnicodeTTF`는 오류를 표시하지 않고 v2.74 버전의 측정 정보만을 사용하여 계속 진행합니다. 이 경우, 사용하는 리더는 모든 코드 포인트에 대해 `/DW = 1000`을 사용합니다. 데이터 손상은 발생하지 않도록, 모든 멀티바이트 읽기 과정에서 테이블의 경계를 확인합니다.

2026-05-18 Version 2.74.0

  • THotPDF.RegisterUnicodeTTF 함수가 추가되었습니다. 이 함수는 파일 기반으로 v2.70.0 버전의 RegisterUnicodeFontDict 함수를 감싸서 작동하며, TTF/OTF 폰트를 로드하고, head, hhea, OS/2, post 및 name 테이블을 파싱합니다. 또한 FUnit 메트릭을 PDF 디자인 단위(em당 1000)로 변환하고, 변환된 값을 RegisterUnicodeFontDict 함수에 전달하여 완전한 Type 0 / CIDFontType2 + Identity-H 복합 폰트 딕셔너리를 생성합니다. 반환된 딕셔너리는 SetFormUnicodeFontDict 함수에 바로 사용할 수 있으며, 호출자는 폰트의 정확한 메트릭 값이나 SFNT 바이너리 형식에 대한 지식이 필요하지 않습니다.
  • API: RegisterUnicodeTTF(FontPath, LogicalName=""). FontPath은 .ttf 또는 .otf 파일의 절대 경로 또는 상대 경로입니다. LogicalName은 v2.75 이상 버전에서 사용되며, 동일한 PostScript 이름을 가진 글꼴을 구별하는 데 사용될 수 있습니다.
  • 테이블 파싱: head (unitsPerEm, 글꼴 경계 상자 xMin/yMin/xMax/yMax (FUnits 단위)), hhea (상승 높이, 하강 높이 (FUnits 단위)), OS/2 (usWeightClass를 사용하여 /StemV 추정, sCapHeight, 이탤릭 비트를 위한 fsSelection), post (이탤릭 각도 (FIXED 16.16 -> 각도), isFixedPitch -> /Flags 비트 1), name (Windows 또는 Mac 플랫폼의 PostScript 이름 (nameID 6), nameID 4의 전체 이름으로 대체). 모든 테이블의 오프셋/길이에 대한 경계 검사 및 모든 멀티바이트 읽기에 대한 경계 검사를 수행하여, 손상된 글꼴이 메모리 오류가 아닌 명확한 예외로 나타나도록 합니다.
  • 자동으로 파생된 메트릭: `/FontBBox`의 L/B/R/T 값은 PDF 디자인 단위로 조정되고, `/Ascent`와 `/Descent` 값도 조정됩니다. `/CapHeight`는 OS/2 테이블의 `sCapHeight` 값에서 가져오며, 이전 버전의 OS/2 테이블의 경우 `/Ascent` 값을 사용합니다. `/ItalicAngle`은 `post.italicAngle` 값에서 가져오며, `/StemV`는 `50 + (usWeightClass - 400) / 5`로 추정되며, [50, 250] 범위로 제한됩니다. `/Flags`는 `Symbolic` 및 `FixedPitch` (PostScript 정보에 따라)와 `Italic` (fsSelection 비트 0이 설정되었거나 `italicAngle`이 0이 아닌 경우)을 포함합니다. `/BaseFont`는 파싱된 PostScript 이름을 사용하며, 이름 테이블에서 유효한 값을 찾을 수 없는 경우 `"UnnamedTTF"`를 사용합니다.
  • 오류 발생 시 자세한 예외가 발생합니다. 누락된 파일, 불가능한 크기(12바이트 미만 또는 64MB 초과), 인식되지 않는 sfntVersion(0x00010000이어야 함 / 'OTTO' / 'true' / 'typ1'), 필수 테이블 누락(head / hhea / OS/2 / post / name), 필요한 필드에 비해 테이블 크기가 너무 작음.
  • 이 부분에는 다음 내용이 포함되지 않습니다(v2.75 이상에서 구현 예정): hmtx의 `/W` 어드밴스 폭 배열(numGlyphs를 위한 maxp 및 Unicode를 글리프로 매핑하기 위한 cmap이 필요함. 현재 v2.65의 다중 줄 텍스트 줄 바꿈은 0.5/1.0 휴리스틱을 사용함), cmap에서 생성된 ToUnicode CMap(현재 v2.56+의 Identity-H 매핑은 CID가 Unicode 코드 포인트와 같다고 가정함), 원시 글꼴 바이트를 `/FontFile2` 스트림으로 포함, 그리고 글꼴 서브세팅. v2.74.0에서는 읽기 프로그램이 여전히 자체 글꼴 매칭 메커니즘을 통해 `/BaseFont` 이름을 확인해야 합니다.
  • smoke_unicode_ttf.dpr 파일은 Windows 시스템 글꼴을 로드합니다 (순서대로 %SystemRoot%\Fonts 폴더에서 arial.ttf, segoeui.ttf, times.ttf, verdana.ttf 파일을 검색). 또한 RegisterUnicodeTTF 함수가 Type 0 딕셔너리를 반환하는지 확인하고, 파일에서 파싱된 메트릭 정보를 포함하는지 검증합니다. 검증기는 결과적으로 생성된 /BaseFont가 임시 자리 표시자가 아닌지, 그리고 FontBBox, Ascent, Descent, ItalicAngle 값이 실제 글꼴에 대해 적절한 범위 내에 있는지 확인합니다.

2026-05-18 Version 2.73.0

  • Added Unicode UAX #9 simplified W5 (European Terminator adjacent to European Number) for RTL paragraphs. Fixes the visible bug where Arabic text with currency / percent symbols — "$12.50", "50%", "€100", "شار 12.50$ ريال" — left the currency or percent glyph stranded at the boundary between the digit substring and the surrounding RTL text. With v2.73 W5, ETs adjacent to digits join the digit run and reverse with the digits, preserving the currency-and-number unit as one LTR substring inside the RTL paragraph.
  • W5 ETs (코드 포인트 집합: U+0023 # (숫자 기호), U+0024 $ (달러 기호), U+0025 % (퍼센트 기호), U+00A2..U+00A5 (¢ £ ¤ ¥), U+00B0 ° (도 기호), U+00B1 ± (플러스-마이너스 기호), U+066A ٪ (아랍어 퍼센트 기호), U+2030..U+2031 (‰ ‱ 퍼밀/퍼텐천), U+20A0..U+20CF (통화 기호 블록, 여기에는 € ₹ ₽ ₩ 등이 포함됨)). 양쪽 EN 옆에 인접한 ET 시퀀스 중 가장 긴 것은 NSM을 제외하고 EN으로 변환됩니다.
  • HotPDF의 간소화된 W5 기능은 또한 사양의 EN(영어) 전용 규칙에 더하여 AN(아랍-인디아 숫자)에 인접한 ET(Entity)를 AN으로 변환합니다. 이를 통해 ASCII 및 아랍-인디아 숫자 환경의 대칭성을 유지하여 "٥٠٪" (아랍-인디아 숫자 50 + 아랍 퍼센트)에서 퍼센트 기호가 "50%"에서 ASCII 퍼센트 기호를 사용하는 것과 동일하게 처리됩니다.
  • Concrete fix: "شار $12.50 ريال" (logical UTF-16 0634 0627 0631 0020 0024 0031 0032 002E 0035 0030 0020 0631 064A 0627 0644). v2.72 output: 0644 0627 064A 0631 0020 0031 0032 002E 0035 0030 0024 0020 0631 0627 0634 — the $ glyph stranded at memory position 11, between the digit substring and the trailing space, reading awkwardly. v2.73 output: 0644 0627 064A 0631 0020 0024 0031 0032 002E 0035 0030 0020 0631 0627 0634 — "$12.50" intact as one LTR substring inside the RTL flow.
  • BIDI_Class 테이블 수정: U+066A 아랍어 퍼센트 기호가 bcAL에서 bcOther로 이동되었습니다(W5 ET 패스가 이를 감지하고 변환할 수 있도록). 아랍어 블록 조회에는 이제 숫자 범위(bcAN), 하라카트/샤다 블록(bcNSM), 알레프 칸자리야(bcNSM), 소수/천 단위 구분 기호(bcAN) 및 퍼센트 기호(bcOther + W5를 통한 ET)에 대한 예외가 적용되었습니다.
  • 파이프라인 순서: W1 NSM 상속 (LTR 경로는 명시적, RTL은 암시적) -> W4 숫자 사이의 ES/CS -> W5 숫자 옆의 ET -> I2 레벨 할당. W5는 W4 다음에 실행되므로, W4에 의해 변환되어 EN이 된 구분 기호는 W5에서 다음 단계에서 "EN 옆"으로 올바르게 식별됩니다. 복잡한 숫자-구분 기호-통화 표현식 내의 여러 규칙 상호 작용은 단일 파이프라인 탐색으로 해결됩니다.
  • v2.72 출력과 동일한 바이트로 유지됩니다. 기존 v2.59-v2.72 버전의 모든 기능(RTL 아랍어/히브리어/SMP RTL/NSM 위치 조정/LTR 단락 재정렬/숫자 처리/W4)은 바이트 수준에서 변경되지 않았습니다.
  • UAX #9 관련 작업(W6/W7 정리, UAX #9 BD16 스택 스캔을 통한 N0 괄호 쌍 처리, N1/N2 중립 해상도, OpenType GSUB 아랍어/시리아어 문맥적 결합, 파일 기반 RegisterUnicodeTTF)은 아직 완료되지 않았습니다.

2026-05-18 Version 2.72.0

  • Added Unicode UAX #9 simplified W4 (ES / CS between same-typed digits) for RTL paragraphs. Fixes the visible bug where Arabic text with formatted numbers — "السعر 12,345 ريال" (price with thousands comma), "12.50" (decimal point), "12:30" (time colon) — split the digit run at the separator in the reversed /Tj output, producing visually-broken numbers that read backwards within the RTL flow. With v2.72 W4 the separator joins the digit run, both reverse together once and then reverse together again at the whole-string pass, preserving the digit + separator logical order inside the RTL paragraph.
  • W4 구분 기호 인식: 유럽 구분 기호 U+002B (+) / U+002D (-), 일반 구분 기호 U+002C (,) / U+002E (.) / U+002F (/) / U+003A (:) / U+00A0 (NBSP), 그리고 아랍어 일반 구분 기호 U+060C (아랍어 쉼표). 각 기호는 두 개의 EN(영문) 기호 사이에 있으면 EN으로, 두 개의 AN(아랍어) 기호 사이에 있으면 AN으로 변환됩니다. 혼합된 기호(EN + AN 또는 숫자 + 숫자 아님)의 경우, 이전과 같이 bcOther / level-1 / surrounding-RTL 스트림에서 구분 기호는 변경되지 않습니다. UAX #9의 단순화된 버전 vs 전체 버전: NSM(Non-Separator Mark)을 확인하여 처리합니다(구분 기호 근처의 NSM은 W4 조회를 방해하지 않음). 그러나 여러 개의 구분 기호가 연결된 경우, 사양에서 정한 "단일" 구분 기호 제한 대신 각 위치별로 변환됩니다(실제 숫자에서 인접한 구분 기호가 있는 경우는 드물기 때문에 실제 영향은 적습니다).
  • Concrete fix: "شار 12,345 ريال" (logical UTF-16 starts with Arabic letters, then space, "1" "2" "," "3" "4" "5", then space, then Arabic letters). v2.71 previous output: 0644 0627 064A 0631 0020 0035 0034 0033 002C 0031 0032 0020 0631 0627 0634 — digits split at the comma, reversed within each fragment ("345" before "12"), reads as "345,12" inside the LTR substring user perception. v2.72 fixed output: 0644 0627 064A 0631 0020 0031 0032 002C 0033 0034 0035 0020 0631 0627 0634 — "12,345" intact as one LTR substring, user reads it naturally in numeric order.
  • BIDI_Class 테이블 수정 (v2.72.0): U+066B 아랍 숫자 구분 기호 및 U+066C 아랍 천 단위 구분 기호는 이제 UnicodeData에 따라 bcAN (반환 값 5)으로 분류되며, 이전에 bcAL로 분류되었습니다. 이러한 구분 기호는 아랍 숫자 서식의 일부로 정의되어 있으므로, L2 재정렬 시 아랍-인디트 숫자 그룹에 자연스럽게 포함되며 W4 패스가 필요하지 않습니다. U+066A 아랍 퍼센트 기호는 이제 bcAL (임시)로 분류됩니다 (ET/유럽 숫자 종료 처리 기능은 W5로 연기).
  • 내부 리팩터링: `_ApplyUAX9L2Reversal` 함수의 레벨 할당 단계에서, UTF-16 코드 유닛 위치별로 명시적인 `Classes[]` 병렬 배열을 생성합니다 (각 위치에 1바이트). 이를 통해 W4 패스가 이웃 클래스를 확인하는 과정에서 코드 포인트를 다시 디코딩하지 않고도 정보를 얻을 수 있습니다. 서로 연결된 코드 포인트 쌍은 `Classes[]` 및 `Levels[]` 배열의 바이트를 하이 및 로우 부분에서 공유합니다. `_ApplyUAX9L2ReversalLTRPara`에 대한 동일한 리팩터링은 보류됩니다 (W4는 단순화된 단일 임베딩 레벨 모델에서 EN/AN이 기본 레벨 0에 머무르기 때문에 LTR 단락에서는 눈에 띄는 영향을 미치지 않습니다).
  • v2.66부터 v2.71까지 출력되는 순수 RTL/LTR/혼합 텍스트는 동일한 유형의 숫자가 W4 구분 기호 없이 연결되어 있을 때 바이트 단위로 동일합니다. 기존 v2.59-v2.71 버전의 모든 기능(RTL 아랍어/히브리어/SMP RTL/NSM 위치 조정/LTR 단락 재정렬/숫자 처리/감지 기능)은 바이트 단위로 안정적으로 유지됩니다.
  • UAX #9 관련 작업 (EN에 인접한 W5, W6/W7 정리, UAX #9 BD16 스택 스캔을 통한 N0 괄호 쌍 처리, N1/N2의 단순화된 중립 해상도, OpenType GSUB 아랍어/시리아어 문맥적 결합, 파일 기반 RegisterUnicodeTTF)이 아직 남아 있습니다.

2026-05-18 Version 2.71.0

  • 아랍어/히브리어 텍스트 재정렬 시 NSM(non-spacing mark) 위치 오류를 수정했습니다. 이전에, 단순한 전체 문자열 반전으로 인해 결합 문자(아랍어의 하라카트, 예를 들어 파타/카스라/담마/샤다; 히브리어의 니크굿, 예를 들어 셰바/카마츠/파타; U+0300..U+036F 블록의 라틴어 결합 부호)가 반전된 /Tj 스트림에서 해당 기본 문자의 반대쪽에 위치하게 되었습니다. PDF 리더의 결합 부호 렌더러는 표시 순서에서 이전 글리프에 결합 부호를 연결하여 잘못된 기본 문자에 연결되었습니다. 나타나는 문제는 다음과 같습니다. "ALEF + FATHA + BA" (아랍어)에서 파타가 BA 글리프에 표시되었지만 ALEF에는 표시되지 않았습니다.
  • UAX #9 W1 간소화된 NSM 상속 기능이 추가되었으며, 세 가지 L2 재정렬 알고리즘에서 공유하는 그룹 인식 역방향 패스가 구현되었습니다 (RTL 단락 2단계 + 3단계, LTR 단락 단일 패스). 역방향 패스는 이제 [base, NSM*]를 하나의 단위로 처리합니다. 오른쪽에서 왼쪽으로 처리할 때, NSM은 스택에 저장되고, 다음 비-NSM 베이스 요소가 출력될 때마다 원래 논리적 순서대로 스택에서 제거됩니다. 서로게이트 쌍 코드는 동일한 역방향 패스에서 그대로 유지되며, SMP 범위의 NSM(드물게 발생)은 대칭적으로 처리됩니다.
  • 구체적인 수정 사항: 이전에 "ALEF + FATHA + BA" (논리적 UTF-16 0623 064E 0628)가 0628 064E 0623 (전체 역순, FATHA가 BA와 ALEF 사이에 위치)으로 출력되었습니다. v2.71.0 버전에서 NSM(Noto Sans Mongolian) 인식 기능을 통해 동일한 입력이 0628 0623 064E로 출력됩니다. 즉, BA가 왼쪽에, ALEF가 중앙에, FATHA가 ALEF 뒤에 위치하므로 렌더러가 이를 올바른 기본 글자에 연결합니다.
  • 내부 BIDI_Class 테이블이 확장되어 주요 결합 부호 블록에 대해 bcNSM 클래스(반환 값 6)가 추가되었습니다. 이러한 블록에는 다음이 포함됩니다. 일반 결합 부호 U+0300..U+036F (라틴/일반 악센트), 히브리어 니크굿 U+0591..U+05BD, 그리고 분산된 U+05BF / U+05C1..U+05C2 / U+05C4..U+05C5 / U+05C7 항목 (히브리어 R 범위에서 추출), 아랍어 하라카트 U+064B..U+065F 및 알레프 칸자리야 U+0670 (아랍어 AL 범위에서 추출). NSM은 여전히 단락 방향 P2/P3의 초기 강세 스캔 중에 건너뜷힙니다.
  • LTR 문단에서는 초기 레벨 할당 후 명시적인 W1 NSM 레벨 상속 단계를 실행합니다. 각 NSM은 이전의 NSM이 아닌 코드 포인트의 레벨을 상속하므로, AL 베이스 뒤에 오는 아랍어 NSM은 해당 베이스의 레벨 1 실행에 포함됩니다. RTL 문단에서는 레벨이 암시적으로 상속됩니다 (NSM과 R/AL 모두 단순화된 단일 임베딩 레벨 모델에서 레벨 1로 해석됨). 따라서 별도의 W1 단계가 필요하지 않습니다.
  • 순수 RTL/LTR/혼합 입력에서 NSM(Non-Spacing Marks)이 없는 경우, v2.66/v2.67/v2.68/v2.69/v2.70 출력과 바이트 단위로 동일합니다 (NSM이 없다는 것은 동작 변경이 없음을 의미). 기존 v2.59 RTL 아랍어, v2.66 LTR-in-RTL, v2.67 LTR-para, v2.68 EN-AN, v2.69 SMP-RTL 테스트 모두 바이트 단위로 안정적입니다.
  • UAX #9 관련 작업의 나머지 부분(W3-W7의 상세한 약형 전환, N0-N2의 중립 및 괄호 쌍 해결, OpenType GSUB 아랍어/시리아어 문맥적 결합, 파일 기반 RegisterUnicodeTTF)이 아직 완료되지 않았습니다.

2026-05-18 Version 2.70.0

  • THotPDF.RegisterUnicodeFontDict 도우미 함수가 추가되었습니다. 이 함수는 PDF 1.7 ISO 32000-1 9.7 / 9.7.6 Type 0 / CIDFontType2 및 Identity-H 복합 글꼴 사전 항목을 한 번의 호출로 구성합니다. v2.56.0 버전부터 SetFormUnicodeFontDict AcroForm /AP 경로를 사용하는 사용자는 더 이상 CIDSystemInfo / FontDescriptor / CIDFontType2 / Type 0 / Identity-H 하위 사전 항목을 직접 코딩할 필요가 없습니다. 이 함수는 SetFormUnicodeFontDict에 전달할 수 있는 간접 THPDFDictionaryObject를 반환합니다.
  • API: RegisterUnicodeFontDict(BaseFont, FontBBoxL/B/R/T, Ascent, Descent, CapHeight, ItalicAngle, StemV, Flags, DefaultWidth). 모든 측정 값은 기본적으로 합리적인 값을 가집니다 (CJK/아랍어 내장 글꼴의 경우: FontBBox [-1000 -300 2000 1300], Ascent 1000, Descent -300, CapHeight 750, StemV 100, Flags 4 = Symbolic, DW 1000). Latin/히브리어/키릴 문자 글꼴의 경우 더 작은 bbox와 non-symbolic Flags = 32로 개별적으로 재정의할 수 있습니다.
  • 사전 구조는 smoke_acroform_cid_rtl / smoke_bidi_*에서 v2.59-v2.69 전반에 걸쳐 사용되는 사양을 준수하는 Type 0 + CIDFontType2 레이아웃과 일치합니다. 여기에는 Adobe / Identity / Supplement 0 CIDSystemInfo, 모든 필수 항목이 포함된 FontDescriptor, Identity-H 인코딩, DescendantFonts 배열의 CIDFontType2 하위 항목, 기본 문자 너비에 대한 /DW가 포함됩니다. /CIDToGIDMap은 지정되지 않은 경우 기본적으로 /Identity로 설정되며 (CID == GID), 이는 Identity-H + Adobe-Identity-0 순서를 의미합니다.
  • 향후 v2.71 이상 버전에서는 파일 기반의 `RegisterUnicodeTTF` 기능을 추가할 예정입니다. 이 기능은 `.ttf` 또는 `.otf` 파일을 분석하여 실제 측정값과 `hmtx` 및 `W` 어드밴스 폭을 추출하여 완벽한 래핑 계산을 수행하고, 글꼴을 `/FontFile2`로 임베드하며, `cmap`에서 ToUnicode CMap을 생성하고, 구조적인 부분을 위해 내부적으로 `RegisterUnicodeFontDict`를 호출합니다.

2026-05-18 Version 2.69.0

  • U+10800..U+10FFF 범위의 보충 다국어 평면(SMP) 내 Unicode BIDI_Class 참조 테이블을 확장하여 오른쪽에서 왼쪽으로 쓰는 문자 블록을 지원합니다. 단락 방향 감지 및 L1-L2 재정렬 기능은 이제 페니키아 문자, 제국 아람어, 팔미렌어, 나바테아 문자, 하트라어, 리디아어, 메로이틱 상형 문자/필기 문자, 카로슈티 문자, 고대 남아라비아어, 고대 북아라비아어, 마니교 문자, 아베스탄어, 명문 파르티아어/파블라비어, 시편 파블라비어, 고투르크어, 고헝어, 하니피 로힝야어(AL, 현재 미얀마에서 로힝야어를 사용하는 문자), 가라이어, 예지드어, 아랍어 확장 C(AL), 고대 소그디아어, 소그디아어, 고대 위구르어, 호라즘어 및 엘리마이어를 올바르게 인식합니다.
  • SMP RTL 문단은 이제 DetectBidiParagraphDirection을 통해 자동으로 RTL로 인식되며 (첫 번째 강한 문자 스캔은 서로게이트 쌍을 처리하고 적절한 R/AL 클래스와 일치시킵니다), v2.66 RTL L1-L2 재정렬을 수행하여 시각적으로 UTF-16BE Tj 출력을 생성합니다. EnableLTRParaReorder가 설정된 경우, 포함된 SMP RTL 서브스트링을 포함하는 LTR 문단은 해당 서브스트링을 추가로 반전시킵니다 (v2.67 옵션 기능); 그렇지 않으면 논리적인 순서로 출력되며, 최종 리더의 내재된 BIDI 기능을 사용합니다.
  • 서로게이트 쌍 보존 기능은 모든 L2 역순 처리 과정에서 계속 유지됩니다. SMP RTL 코드 포인트는 `/Tj` 헥스 스트림에서 그대로 높은 바이트와 낮은 바이트 쌍으로 유지되는 반면, 주변 문단은 올바르게 재정렬됩니다.
  • v2.67 버전에서, smoke 테스트 (smoke_bidi_ltr_reorder)의 assertion #7은 U+10840 IMPERIAL ARAMAIC LETTER ALEPH를 사용하여 "SMP 코드 포인트가 LTR 단락에서 bcOther로 처리됨"을 보여주었습니다. 이번 릴리스에서 해당 assertion은 현재 올바르게 수정된 bcR 분류를 반영하도록 업데이트되었습니다. 즉, LTR 단락에서 U+10840은 레벨 1의 R/AL 런의 일부가 되며, 인접한 히브리어/아랍어 문자열과 함께 시각적 위치에 맞춰 재정렬됩니다.
  • UAX #9 관련 작업이 아직 남아 있습니다 (W1 NSM 상속 + W3-W7 약한 유형 전환 + N0-N2 중립 + 괄호 쌍 해결 + I1 명시적 수준 해결 + OpenType GSUB 아랍어/시리아어 문맥적 결합). SMP RTL 지원이 완료됨에 따라, 모든 표준화된 Unicode RTL 스크립트가 이제 단락 방향 및 기본 L1-L2 재정렬에 대해 올바르게 분류됩니다.

2026-05-18 Version 2.68.0

  • Fixed visible direction bug for digits embedded in Arabic / Hebrew paragraphs. Added Unicode UAX #9 weak-class BIDI_Class entries for European digits (EN, U+0030..U+0039) and Arabic-Indic digit ranges (AN, U+0660..U+0669 + U+06F0..U+06F9), with simplified UAX #9 I2 + L2 level assignment: in an RTL paragraph these digit codepoints now get resolved level 2 (same as embedded LTR runs) rather than level 1 alongside the surrounding RTL text. The two-pass L2 reorder then preserves their logical order inside the visual RTL flow, matching the spec-correct "شارع 12345" user reading even when the paragraph is rendered LTR for the PDF /Tj stream.
  • Concrete fix: an input "شار 12345" (logical UTF-16 0634 0627 0631 0020 0031 0032 0033 0034 0035) previously emitted as the Tj operand 0035 0034 0033 0032 0031 0020 0631 0627 0634 (whole-string reverse - digits inverted, the visible bug). With the v2.68 fix the same input emits 0031 0032 0033 0034 0035 0020 0631 0627 0634 - digits stay 1-2-3-4-5 in reading order while the Arabic word still renders in visual RTL.
  • DetectBidiParagraphDirection은 이제 UAX #9 P2에 따라 EN과 AN을 약한 방향으로 처리합니다. 숫자만 있거나 숫자로 시작하는 문단은 더 이상 숫자에 의해 RTL로 고정되지 않습니다. 여전히 첫 번째 강한 문자(L/R/AL)가 우선합니다. 비어 있거나 약한 문자만 있는 입력은 여전히 P3에 따라 LTR로 처리됩니다. 테스트에서는 순수 숫자는 LTR을 반환하고, 숫자 다음에 아랍어가 오면 RTL을 반환하며(아랍어 AL이 첫 번째 강한 문자임), 숫자 다음에 라틴어가 오면 LTR을 반환합니다(라틴어 L이 첫 번째 강한 문자임).
  • 아랍어 블록 범위 U+0600..U+06FF가 조회 테이블에서 분할되어 두 개의 범위가 bcAN으로 분리되었습니다. 주변 범위인 U+0600..U+065F + U+066A..U+06EF + U+06FA..U+06FF는 bcAL로 유지됩니다. 다른 아랍어 블록의 코드 포인트(구두점, 퍼센트/퍼밀 기호, 통화 등)는 현재 bcAL 분류를 유지합니다. 더 세분화된 약한 클래스 처리(ET / CS / ON / NSM)는 향후 릴리스에서 W1-W7 / N0-N2 파이프라인과 함께 제공될 예정입니다.
  • v2.66/v2.67 출력과 동일한 바이트 스트림을 가진 오른쪽에서 왼쪽(RTL) 입력에서 숫자 렌더링이 발생하지 않습니다 (W 클래스 전환이 트리거되지 않음). 왼쪽에서 오른쪽(LTR) 단락에는 영향을 미치지 않습니다 (숫자는 이미 단락의 기본 방향에 따라 LTR로 렌더링됨). 이 수정 사항은 AutoDetectFormBidi 또는 FormUnicodeRTL을 사용하고 UseUAX9LevelReversal=True (기본값)로 설정된 기존 모든 호출에서 자동으로 적용됩니다.
  • UAX #9 및 GSUB 범위(W1 NSM 상속 + 전체 W3/W4/W5/W6/W7 + N0-N2 범위 + I1 명시적 수준 해결 + OpenType GSUB 아랍어/시리아어 문맥적 결합 + SMP RTL 스크립트 BIDI_Class)에 대한 작업이 아직 남아 있습니다.

2026-05-18 Version 2.67.0

  • LTR 문단 내에 포함된 RTL 서브스트링에 대한 유니코드 UAX #9 L2 재정렬 기능을 추가했습니다. 새로운 속성 `THotPDF.EnableLTRParaReorder` (기본값: False)를 통해 호출자가 규격 준수, 리더 독립적인 `/AP` 출력을 사용할 수 있습니다. 즉, 포함된 히브리어/아랍어 서브스트링을 가진 LTR 문단은 `/AP` 생성 시 재정렬되므로, 소비자 리더는 논리 순서의 RTL 서브스트링에 대한 자체 BIDI 처리를 수행할 필요가 없습니다.
  • v2.66.0 버전과 동일한 단일 패스 알고리즘을 사용하여 RTL 문단에 대한 L1-L2 수준을 처리합니다. LTR 문단의 기본 수준은 0이며, 각 "strong-R" 또는 "strong-AL" 코드 포인트는 수준 1로 처리되고, 나머지는 수준 0으로 유지됩니다. UAX #9에 따르면 L2에서 가장 낮은 홀수 수준은 1이므로, 루프는 한 번만 실행됩니다. 각 최대 수준 1 서브 문자열(연속된 R/AL 시퀀스)을 역순으로 변경합니다. LTR 문자 및 약하거나 중립적인 문자는 변경되지 않고 그대로 복사됩니다. 서로게이트 쌍은 역순 변경 과정에서 유지됩니다.
  • THotPDF.ApplyUAX9L2ReversalLTRPara 공개 메서드는 새로운 알고리즘을 독립적으로 제공합니다 (UTF-8 입력, UTF-8 출력). 이는 v2.66.0 버전의 ApplyUAX9L2Reversal 메서드와 다릅니다. v2.66 버전의 ParagraphRTL=False 경로는 이전과 동일하게 동작하므로, v2.66 버전의 동작 방식을 사용하는 호출자는 동일한 결과를 얻습니다. LTR 방향으로 재정렬하려면 새로운 메서드를 사용하십시오.
  • `EnableLTRParaReorder`의 기본값은 `False`이며, 이를 통해 LTR 문단 호출 시 v2.59부터 v2.66까지의 바이트 단위로 동일한 `/AP` 출력을 유지합니다. `UseUAX9LevelReversal`이 `False`인 경우, 이 기능은 영향을 미치지 않습니다 (v2.59의 단순 역전 기능은 LTR 문단을 재정렬하지 않음). 두 기능은 다른 경우에는 독립적으로 작동합니다.
  • UAX #9 W1-W7 약형 전환, N0-N2 중립 문자, 괄호 쌍 해결, I1-I2 명시적 수준 해결 및 OpenType GSUB 서체 형상 기능은 v2.68 이상 버전에서 지원됩니다.

2026-05-18 Version 2.66.0

  • AcroForm 유니코드 표현 스트림에 대한 UAX #9 L1-L2 런 인식 역순 처리 기능을 추가했습니다. 새로운 속성 THotPDF.UseUAX9LevelReversal (기본값: True)은 v2.59.0 버전의 단순한 전체 문자열 역순 처리 방식을, RTL 문단 내에 포함된 LTR 부분 문자열의 내부 논리적 순서를 유지하는 규격에 맞는 2단계 L2 재정렬 방식으로 대체합니다.
  • Concrete fix: an input "<Hebrew>AB" (logical UTF-16 05D0 05D0 0041 0042) previously emitted as the Tj operand hex 0042 0041 05D0 05D0 ("BAאא"), which inverts the embedded LTR "AB" - wrong per UAX #9. With L1-L2 active the same input now emits 0041 0042 05D0 05D0 ("ABאא"). Pure-RTL input with no L runs (e.g. the v2.59.0 pre-shaped Arabic smoke) remains byte-identical to the legacy naive reverse.
  • THotPDF.ApplyUAX9L2Reversal 공개 메서드는 새로운 알고리즘을 독립적인 도구로 제공하며 (UTF-8 입력, UTF-8 출력), 이를 통해 호출자는 자체 렌더링 스트림을 만들거나 /AP 생성을 위한 재정렬을 미리 보기를 할 수 있습니다.
  • 이 섹션에서 사용되는 UAX #9 I1 + L2의 단순화된 단일 임베딩 레벨 서브셋은 다음과 같습니다. RTL 단락에서 각 강한 왼쪽(strong-L) 코드 포인트는 레벨 2로 처리되며, 나머지는 (오른쪽, 왼쪽, 약한, 중립, 서로게이트) 모두 레벨 1로 유지됩니다. 그런 다음 L2는 먼저 레벨 2의 실행을 역전시켜 임베디드된 LTR 서브 문자열의 논리적 순서를 복원하고, 마지막으로 전체 문자열의 레벨 1 세그먼트를 역전시켜 시각적인 RTL 레이아웃을 생성합니다. 서로게이트 쌍은 두 단계 모두에서 유지됩니다.
  • UAX #9의 W1-W7 (약한 유형 전환) + N0-N2 (중립 및 괄호 쌍) + I1-I2 (명시적 수준 해상도) + 임베디드 RTL 텍스트가 포함된 LTR 단락에 대한 재정렬은 v2.67+ 버전에서 지원됩니다. v2.66.0 버전은 다중 문자 LTR 서브스트링이 포함된 RTL 단락에서 발생하는 가장 흔한 문제를 해결합니다.
  • UseUAX9LevelReversal의 기본값은 True입니다. False로 설정하면 v2.59.0 버전의 단순한 전체 문자열 역순 방식을 사용하여 이전 버전과 동일한 출력을 얻을 수 있습니다. 두 방식 모두 FormUnicodeRTL 및 AutoDetectFormBidi를 동일한 방식으로 처리합니다.

2026-05-18 Version 2.65.0

  • AcroForm 유니코드 AP 외형 스트림에 대한 Unicode Standard Annex #9의 단락 방향 자동 감지 기능을 추가했습니다. 새로운 속성인 THotPDF.AutoDetectFormBidi는 v2.59.0 버전부터 제공되던 FormUnicodeRTL 수동 토글 대신, BuildUnicode*FieldContent 도우미 함수(단일 행, 다중 행, 조합)에서 호출 시 단락 방향을 자동으로 감지하도록 변경되었습니다. 이를 통해, 수동 플래그 전환 없이도 하나의 문서에서 LTR 및 RTL 필드를 혼합하여 사용할 수 있습니다.
  • 텍스트 방향은 입력에서 가장 먼저 나타나는 강한 문자(UAX #9 규칙 P2 + P3)를 검색하여 결정하며, 이를 BIDI_Class L (왼쪽), R (오른쪽에서 왼쪽), 또는 AL (아랍 문자)로 분류합니다. 강한 R 또는 AL 문자는 단락을 RTL (오른쪽에서 왼쪽)로 고정하고, 강한 L 문자는 LTR (왼쪽에서 오른쪽)로 고정합니다. 강한 문자가 없는 단락은 P3에 따라 기본적으로 LTR로 설정됩니다.
  • BIDI_Class가 인식되었습니다: 강한 왼쪽-오른쪽 (Strong L) - ASCII, Latin, Latin Extended, Greek, Coptic, Cyrillic, Armenian, CJK Unified Ideographs, Hangul, Hiragana, Katakana, Yi. 강한 오른쪽-왼쪽 (Strong R) - 히브리어 블록 (U+0590..U+05FF), 히브리어 표현 형태 (U+FB1D..U+FB4F), N'Ko, Samaritan, Mandaic. 강한 양방향 (Strong AL) - 아랍어 블록, 아랍어 보충, 아랍어 확장-A, Syriac, Thaana, 아랍어 표현 형태 A + B (U+FB50..U+FDFF + U+FE70..U+FEFF). 검색 중에는 서로게이트 쌍과 약하거나 중립적인 문자(숫자, 구두점, 공백)가 건너뜷니다.
  • THotPDF 클래스의 DetectBidiParagraphDirection 공개 메서드는 방향을 미리 계산하려는 호출자에게 방향 감지 기능을 제공합니다 (예: /Lang 태깅, 반전된 중립 출력, 사용자 정의 필드 라우팅). UTF-8 AnsiString을 입력으로 받아 Boolean 값을 반환하며 (True는 오른쪽에서 왼쪽), P3에 따라 빈 입력은 False를 반환합니다.
  • AutoDetectFormBidi의 기본값은 False이며, 기존 v2.59.0-v2.64.0 버전과의 동일한 동작을 유지합니다. True로 설정하면, 해당 설정은 각 호출마다 FormUnicodeRTL을 무시합니다. AutoDetectFormBidi를 비활성화하여 수동 제어를 복원할 수 있습니다.
  • UAX #9의 모든 암시적 레벨, 약한 유형, 중립 브래킷 해상 규칙(규칙 W1-W7, N0-N2, I1-I2, L1-L4) 및 자동 아랍어/시리아어 OpenType GSUB 문맥적 결합 기능은 v2.66 이상 버전에서 제공될 예정입니다. 양방향 문단은 여전히 문단 수준의 방향 외에 수동 개입이 필요합니다.

2026-05-18 Version 2.64.0

  • PDF 1.2 ISO 32000-1 10.5.5 ExtGState의 halftone 화면 (/HT) 항목과 Type 1 spot-function halftone 사전 빌더가 추가되었습니다. 새로운 `THotPDF.RegisterHalftoneType1`은 PDF 1.7 표 76에 정의된 Type 1 halftone 사전 구조를 생성하며, 호출자가 제어하는 CMYK 분리 화면을 사용합니다 (인치당 선 수, 각도, 점 모양, 선택적 정확한 화면 처리, 전송 함수, 설명적인 halftone 이름). `THotPDF.RegisterHalftoneState`와 함께 사용하여 해당 사전 참조를 ExtGState /HT 항목으로 래핑하고, `THPDFPage.SetGraphicsState`에서 사용할 수 있습니다.
  • `/SpotFunction`은 PDF 1.7의 표 78에 정의된 내장된 특정 이름(SimpleDot, InvertedSimpleDot, DoubleDot, InvertedDoubleDot, CosineDot, Double, InvertedDouble, Line, LineX, LineY, Round, Ellipse, EllipseA, InvertedEllipseA, EllipseB, EllipseC, InvertedEllipseC, Square, Cross, Rhomboid, DiamondRhomboid) 또는 호출자가 생성한 특정 함수 사전 참조를 허용합니다. 알 수 없는 내장 이름은 메시지에 전체 사양이 인용되어 오류를 발생시킵니다. 특정 이름과 함수는 서로 배타적입니다.
  • `/TransferFunction`은 선택 사항입니다. 호출자가 제어하는 톤 재현을 위해 `Function` 딕셔너리 참조를 전달하거나, `/TransferFunctionDefault`를 `True`로 설정하여 `/TransferFunction /Identity`를 생성할 수 있습니다 (이것은 기본 설정입니다). 이 두 가지 방식은 상호 배타적입니다.
  • RegisterHalftoneState 함수는 halftone 사전 참조(일반적으로 RegisterHalftoneType1 함수의 반환 값) 또는 HTDefaultName = True를 허용합니다. 이 경우, 소비자 리더의 내장 halftone 설정으로 돌아가는 /HT /Default 이름 리터럴 경로가 사용됩니다.
  • 모든 배출은 문서 버전을 자동으로 PDF 1.2로 업데이트합니다. 빈도는 0보다 커야 하며, 유효하지 않은 스팟 함수 이름은 딕셔너리가 할당되기 전에 오류를 발생시킵니다.
  • v2.65 이상 버전에서 다음과 같은 하프톤 유형이 추가될 예정입니다: Type 5 다중 구성 하프톤, Type 6 / 10 / 16 임계값 스트림 하프톤. Type 1이 구현됨으로써, 매트릭스의 "ExtGState 항목" 후보는 전체 범위를 포괄하는 한 부분으로 제공됩니다.

2026-05-18 Version 2.63.0

  • PDF 1.4 ISO 32000-1 11.6.5 + 11.7.4 ExtGState의 소프트 마스크 및 알파 채널 관련 항목을 추가했습니다. 새로운 THotPDF.RegisterSoftMaskState는 투명도 관련 매개변수인 /SMask 및 /AIS 그래픽 상태를 하나의 ExtGState 딕셔너리로 묶어, 모든 사양 정의 항목에 대한 v2.20.0 + v2.60.0 + v2.61.0 + v2.62.0 + v2.63.0 ExtGState 항목 지원을 완료했습니다 (다중 유형의 /HT 하프톤 스크린은 v2.64 이상에 예정).
  • `/SMask`에는 `/None` 문자열(호출자가 `SMaskNone = True`를 전달할 때 사용되며, 복잡한 합성 후 일반적인 초기화 방식) 또는 간접적인 소프트 마스크 딕셔너리 참조가 포함될 수 있습니다(호출자가 `SMaskDict`를 전달할 때 사용되며, 고급 사용 사례). 이 두 형식은 상호 배타적입니다. 호출자는 소프트 마스크 딕셔너리의 내용과 기본 투명성 Form XObject에 대한 책임을 집니다. v2.64 버전부터는 전용 빌더 도우미가 추가될 예정입니다.
  • /AIS는 현재 알파 값들이 알파 값으로 해석될지 (false) 또는 모양으로 해석될지 (true)를 제어합니다. 기본적으로 AIS = -1인 경우 /AIS 항목을 완전히 건너니다. AIS에 0 또는 1을 전달하면 각각 /AIS false 또는 /AIS true가 출력됩니다. 다른 모든 AIS 값은 설명적인 메시지와 함께 오류를 발생시킵니다.
  • `/SMask` (None 또는 Dict) 또는 `/AIS` 중 하나는 반드시 제공되어야 합니다. 그렇지 않으면 오류가 발생합니다. 또한, 어떤 항목이라도 추가되면 문서가 자동으로 PDF 1.4 버전으로 업데이트됩니다.
  • THotPDFPage.SetGraphicsState을 사용할 때 자동으로 생성된 ExtGState 이름(GS1, GS2 등)을 반환합니다. v2.42.0 버전의 AddImageWithSMask와는 다릅니다. AddImageWithSMask는 단일 XObject 내의 이미지 레벨 알파 채널을 사용하는 반면, 이 기능은 모든 후속 페인팅 연산자에 영향을 미치는 ExtGState 레벨 마스크를 사용합니다.
  • ExtGState 항목은 v2.64 이상 버전에서 지원될 예정입니다. /HT는 halftone screen을 나타내며, Type 1, 5, 6, 10, 16 값을 가질 수 있습니다.

2026-05-18 Version 2.62.0

  • PDF 1.2/1.3 이상 및 ISO 32000-1 11.7.5.4의 ExtGState 블랙 생성 및 언더컬러 제거 항목을 추가했습니다. 새로운 THotPDF.RegisterBlackGenerationState는 CMYK 사전 인쇄 워크플로우에서 RGB에서 CMYK로의 변환이 래스터화 시점에 발생하는 경우, 4개의 함수 참조 그래픽 상태 매개변수(/BG, /BG2, /UCR, /UCR2)를 하나의 ExtGState 딕셔너리로 묶습니다. 이는 신문, 포장 또는 대형 인쇄 생산과 같이 잉크 배치 결정이 출력 장치에 특화된 경우에 일반적입니다.
  • /BG 및 /UCR (PDF 1.2)은 1개의 입력과 1개의 출력을 갖는 함수 사전입니다. /BG2 및 /UCR2 (PDF 1.3 이상)는 함수 사전이거나, 소비자 뷰어의 기본 곡선을 복원하는 문자열 "/Default"입니다. 설정자는 각 함수 슬롯에 대해 THPDFObject를 허용하며, "/Default" 문자열 형식을 사용하는 경우 BG2DefaultName 및 UCR2DefaultName이라는 두 개의 부울 플래그를 사용합니다. 동일한 /BG2 또는 /UCR2 슬롯에 대해 함수 사전과 Default 플래그를 혼합하면 설명적인 메시지와 함께 오류가 발생합니다.
  • /BG, /BG2, /UCR, /UCR2 (Function 또는 Default) 중 하나는 반드시 제공되어야 하며, 모든 항목을 기본값으로 설정하면 오류가 발생합니다. /BG2 또는 /UCR2 항목(Function 또는 Default)이 하나라도 포함되면 PDF 버전이 자동으로 1.3으로 업데이트됩니다.
  • THotPDFPage.SetGraphicsState에서 사용할 자동 생성된 ExtGState 이름(GS1, GS2 등)을 반환합니다. v2.60.0 버전의 RegisterTransferFunctionState(채널별 출력 곡선)와 함께 사용하면 자연스럽게 호환됩니다. 일반적인 CMYK 생산 체인에서는 RGB를 CMYK로 변환하기 위한 BG/UCR ExtGState와 출력 장치에서의 최종 톤 재현을 위한 /TR ExtGState를 등록합니다.
  • v2.63 이상 버전에서 예정된 ExtGState 항목은 다음과 같습니다. /HT는 halftone screen(유형 1, 5, 6, 10, 16)이며, ExtGState 레벨의 /SMask 및 /AIS 소프트 마스크가 포함됩니다.

2026-05-17 Version 2.61.0

  • PDF 1.2/1.3 이상, ISO 32000-1 8.6.5.7 + 8.6.5.8 + 11.7.4 ExtGState 인쇄 제어 항목을 추가했습니다. 새로운 THotPDF.RegisterPrintControlState는 사전 인쇄 환경에 적합한 그래픽 상태 매개변수(/OP, /op, /OPM, /SA, /RI 및 /FL)를 하나의 ExtGState 딕셔너리로 묶어 PDF/X-1/X-3/X-4 생산 워크플로우에 필요한 오버프린트, 스트로크 조정, 렌더링 의도 및 곡선 평활화 제어 기능을 제공합니다.
  • 모든 여섯 가지 매개변수는 독립적으로 선택 사항입니다. 기본값은 다음과 같습니다. Overprint = -1 ( /OP 및 /op 건너뜀), OverprintMode = -1 ( /OPM 건너뜀), StrokeAdjustment = -1 ( /SA 건너뜀), RenderingIntent = '' ( /RI 건너뜀), Flatness < 0 ( /FL 건너뜀). 호출자는 최소한 하나의 항목을 제공해야 하며, 빈 딕셔너리는 오류를 발생시킵니다.
  • PDF 사양에 따라 /OP 및 /op을 함께 설정합니다 (PDF 사양에서는 /op을 /OP로 기본 설정하지만, 엄격한 PDF/X 파이프라인에서는 두 항목을 명시적으로 설정해야 합니다). OverprintMode를 1로 설정하면 PDF 1.3 버전의 CMYK 호환 오버프린트 기능을 활성화하며, 이 경우 어떤 색상 구성 요소가 0이면 투명하게 처리됩니다. 또한 문서 버전을 자동으로 1.3으로 업데이트합니다.
  • RenderingIntent은 'AbsoluteColorimetric', 'RelativeColorimetric', 'Saturation', 'Perceptual'의 네 가지 표준 값을 허용하며, 다른 모든 비어 있지 않은 문자열은 오류를 발생시킵니다. Flatness는 지정된 범위 [0.0..100.0] 내에서만 유효하며, 범위를 벗어나는 값은 오류를 발생시킵니다.
  • THotPDFPage.SetGraphicsState을 사용할 때 자동으로 생성된 ExtGState 이름(GS1, GS2 등)을 반환합니다. v2.20.0 버전의 RegisterExtGState (투명도/블렌드 모드) 및 v2.60.0 버전의 RegisterTransferFunctionState (출력 곡선)와 함께 사용하면 일반적인 PDF/X 설정에서 각 기능을 하나씩 연결할 수 있습니다.
  • 기능 기반 항목(/BG, /UCR, /BG2, /UCR2의 검은색 생성 및 언더컬러 제거) 및 복잡한 /HT 하프톤 스크린과 ExtGState 레벨의 /SMask 소프트 마스크는 향후 개발 범위에 포함됩니다.

2026-05-17 Version 2.60.0

  • PDF 1.3 이상 및 ISO 32000-1 11.7.3.4 ExtGState /TR(전송 함수) 지원이 추가되었습니다. 새로운 THotPDF.RegisterTransferFunctionState 메서드는 래스터화 과정에서 색상을 적용할 때 사용되는 톤 재현 곡선을 포함하는 ExtGState 딕셔너리를 등록합니다. 이 곡선은 v2.52.0 Function Type 0 Sampled LUT(또는 호출자가 생성한 다른 Function 딕셔너리)로 제공되며, 기존의 RegisterSampledFunction 기능을 통해 ICC 프로파일을 사용하지 않고도 정밀하게 조정된 감마/밝기/인쇄 특성 곡선을 만들 수 있습니다.
  • 두 가지 호출 경로:
  • SingleFunc 형식: 하나의 함수가 모든 출력 채널에 적용됩니다 (감마/밝기 조정에 사용).
  • 각 채널 배열 형식: RGB-A 파이프라인의 경우 [TR_R, TR_G, TR_B, TR_A]의 4개 요소로 구성된 배열이고, CMYK 재현 곡선의 경우 [TR_C, TR_M, TR_Y, TR_K]의 배열입니다. PDF 사양에 따라 이 네 슬롯 모두 비어 있지 않아야 합니다.
  • THotPDFPage.SetGraphicsState을 사용할 때 자동으로 생성된 ExtGState 이름(GS1, GS2 등)을 반환합니다. 텍스트, 경로 또는 이미지를 그리기 전에 해당 상태를 적용하여 전송 처리를 수행해야 합니다.
  • 혼합된 호출(SingleFunc이 null이 아니고 PerChannel이 비어 있지 않은 경우)은 예외를 발생시켜 API 수준에서 규격에서 요구하는 상호 배제가 적용되도록 합니다.

2026-05-17 Version 2.59.0

  • AcroForm Unicode /AP에 대한 오른쪽에서 왼쪽 방향 지원이 추가되었습니다 (PDF 1.7 ISO 32000-1 12.7.4.3). 새로운 THotPDF.FormUnicodeRTL 부울 속성이 추가되었으며, 이 값이 참이면 세 가지 Unicode /AP 도우미(단일 행, 다중 행, 조합)가 출력하는 16진수 Tj 연산자에서 UTF-16 코드 단위의 순서를 뒤집어 아랍어/히브리어/시리아어 콘텐츠가 시각적으로 오른쪽에서 왼쪽으로 표시되도록 합니다. UTF-16 서로게이트 쌍은 역전 과정에서 하나의 단위로 유지됩니다 (원래 순서에서 높은 코드가 낮은 코드와 인접하게 유지되므로 고대 문자 형태와 같은 SMP 코드 포인트가 올바르게 표시됩니다).
  • 범위: v2.59.0 버전은 방향 반전 단계만 처리합니다. 호출자는 v2.59.0 버전이 의도적으로 수행하지 않는 두 가지 전처리 작업을 수행해야 합니다. (1) 전체 UAX #9 양방향 알고리즘 해상도 (혼합 LTR / RTL / 숫자 / 중립 콘텐츠) 및 (2) 아랍어 / 시리아어 문맥 기반 결합 (초성 / 중간성 / 말성 / 분리 글리프 형태 선택). 호출자는 AddTextField 함수에 전달하기 전에 아랍어를 해당 Unicode 표현 형태로 미리 변환해야 합니다 (U+FB50..U+FDFF + U+FE70..U+FEFF). 히브리어는 문맥 기반 결합이 없으므로, 사전 변환 없이도 정상적으로 작동합니다.
  • /V (논리적 Unicode 순서)는 변경되지 않았습니다. PDF 텍스트 문자열은 항상 지정된 순서를 가지므로, 표준을 준수하는 텍스트 추출기는 올바른 논리적 순서를 인식합니다. /AP Tj 연산자가 순서를 변경하는 경우는 렌더러가 시각적으로 오른쪽에서 왼쪽으로 텍스트를 그리기 위해서입니다. 이번 릴리스에서는 v2.55.0-v2.59.0 AcroForm 국제 /AP 체인이 완료되었습니다. 여기에는 /RV(서식 있는 텍스트), 단일 행/다중 행/결합 CID 폰트 /AP, 그리고 미리 정의된 RTL(오른쪽에서 왼쪽) 방향 전환이 포함됩니다. UAX #9 및 자동 GSUB 서형화는 v2.60.0 이상 버전에서 지원됩니다.

2026-05-17 Version 2.58.0

  • v2.56.0 및 v2.57.0 버전에서 사용자 제공 Unicode 폰트 /AP 체인을 ffComb 브랜치로 확장했습니다 (PDF 1.7 ISO 32000-1 12.7.4.3 Tx /Ff 비트 25). SetFormUnicodeFontDict에서 Type 0 복합 폰트를 등록하고 ffComb과 ASCII가 아닌 초기 값을 가진 Tx 위젯을 추가하면, HotPDF는 이제 실제 /AP /N 어피어런스 스트림을 생성합니다. 이 스트림은 각 셀에 동일한 너비의 콤(comb) 셀을 사용하여 하나의 CJK 코드 포인트를 배치하며, 각 셀마다 절대적인 Tm 행렬을 사용하고 UTF-16BE 16진수 문자열 Tj 연산자를 사용합니다.
  • UTF-16 서로게이트 쌍(코드 포인트 >= U+10000, 예를 들어 이모지 및 CJK 확장 B/C/D 보충 이디오그래프)은 단일 콤 셀을 차지하며, 이는 Acrobat이 단일 글리프 복합 글꼴 콤 셀을 배치하는 방식과 동일합니다. 셀 중앙 정렬 공식은 v2.46.0부터 사용된 ASCII 콤 브랜치와 동일하므로 시각적 출력은 ASCII 단일 문자 레이아웃과 동일합니다.
  • ASCII 조합 필드는 v2.46.0 출력과 동일한 바이트 값을 유지합니다. `SetFormUnicodeFontDict`를 사용하지 않는 ASCII가 아닌 조합 필드는 여전히 v2.46.0의 빈 AP(Appearance) 플레이스홀더로 대체됩니다(변경 없음). 이번 릴리스에서 v2.55.x-v2.58.0 AcroForm의 국제화된 /AP 체인(단일 행, 다중 행, 조합)이 완료되었습니다. 오른쪽에서 왼쪽(RTL) 양방향 텍스트 모양(UAX #9 + 아랍어 문맥적 결합)은 v2.59.0+ 버전에서 지원됩니다.

2026-05-17 Version 2.57.0

  • v2.56.0 버전에서, 사용자가 제공하는 Unicode 폰트의 /AP 경로를 다중 행 텍스트 필드로 확장했습니다 (PDF 1.7 ISO 32000-1 12.7.4.3 ffMultiline / Tx /Ff 비트 13). SetFormUnicodeFontDict에서 Type 0 복합 폰트를 등록하고 ffMultiline과 ASCII가 아닌 초기 값을 가진 Tx 위젯을 추가하면, HotPDF는 UTF-16 텍스트를 자동으로 줄 바꿈하고, 각 보이는 줄마다 하나의 UTF-16BE 16진수 문자열 Tj를 사용하여 Td/T*와 /TL 리딩을 통해 출력합니다 (v2.46.0의 ASCII 다중 행 레이아웃과 동일).
  • 단어 줄 바꿈 기능은 간단한 방법을 사용합니다. CJK 또는 넓은 코드 단위(U+2E80 이상)의 경우 1em, 좁은 코드 단위(ASCII 범위 및 Latin-1 구두점)의 경우 0.5em을 기준으로 줄 바꿈을 결정합니다. 이렇게 하면 Latin과 CJK 콘텐츠가 섞여 있을 때도 글꼴의 `/W` 배열을 읽지 않고도 적절하게 줄 바꿈됩니다. 하드 줄 바꿈(CR/LF/CRLF)은 유지됩니다. 위젯 영역을 초과하는 줄은 현재 글꼴 크기에서 표시될 수 있는 행 수에 맞춰 잘립니다. 이는 ASCII 다중 줄 기능과 동일한 방식입니다.
  • ASCII 다중 행, ASCII 단일 행, ASCII 조합 방식, 그리고 v2.56.0 버전의 비ASCII 단일 행 방식 모두 바이트 단위로 동일하게 유지됩니다. 비ASCII 조합 방식(ffComb + 다중 바이트 텍스트)은 현재도 v2.56.0 버전의 단일 행 처리기로 연결됩니다. ffComb에 특화된 Unicode 레이아웃 및 RTL 양방향 문자 모양 설정(UAX #9 + 아랍어 문맥 기반 결합)은 v2.58.0 버전부터 적용됩니다.

2026-05-17 Version 2.56.0

  • AcroForm /AP 렌더링을 위한 호출자 제공 유니코드 폰트 지원이 추가되었습니다 (PDF 1.7 ISO 32000-1 12.7.2 + 12.7.4.3). 이전 버전에서는, 필드의 초기 값이 0x80 이상의 바이트를 포함하는 경우, `GenerateTextFieldAP` 경로에서 빈 `/AP` 플레이스홀더가 생성되어, ASCII가 아닌 텍스트는 `/NeedAppearances=true` 재생성(리더에 설치된 폰트에 따라 다름) 또는 v2.55.0의 `/RV` 리치 텍스트 경로(리더의 리치 텍스트 엔진에 따라 다름)를 통해서만 렌더링 가능했습니다. v2.56.0에서는 이러한 문제를 해결했습니다. 이제 호출자는 `SetFormUnicodeFontDict`를 통해 Type 0 /CIDFontType2 + Identity-H 복합 폰트 사전(composite font dict)을 등록할 수 있으며, HotPDF는 등록된 폰트를 `Tf`를 통해 선택하고 값을 UTF-16BE 16진수 문자열로 렌더링하는 실제 `/AP /N` 렌더링 스트림을 생성합니다.
  • THotPDF.SetFormUnicodeFontDict(LogicalName, FontDict) 함수는 논리적 글꼴 이름과 글꼴 딕셔너리 쌍을 등록합니다. 등록 후, AcroForm 레벨의 /DA, 모든 텍스트 필드 위젯의 /DA, 그리고 ASCII가 아닌 텍스트 필드의 초기 값에 대한 /AP 스트림이 모두 논리적 이름으로 변경됩니다. AcroForm의 /DR/Font 딕셔너리는 글꼴 정보를 /Helv 및 /ZaDb와 함께 포함하며, 폼 XObject의 /Resources/Font 하위 딕셔너리도 동일한 간접 글꼴을 참조하므로 AP는 렌더링 시 /DR 해상도에 의존하지 않고 자체적으로 포함됩니다. v2.46.0의 /Helv만 사용하는 동작으로 되돌리려면 빈 값과 nil을 전달하십시오.
  • 새로운 `THotPDF.CreateIndirectFontDict` 함수는, 호출자가 사용자 정의 글꼴/색상/OCG/함수 딕셔너리를 생성할 수 있도록, 새로운 빈 `THPDFDictionaryObject`를 할당하고 이를 간접 PDF 객체로 등록하는 공개 헬퍼 함수입니다. 이 함수는 Type 0 복합 글꼴 딕셔너리를 생성할 때 `SetFormUnicodeFontDict` 함수와 함께 사용하기에 적합합니다.
  • ASCII Tx 필드는 계속해서 `/Helv`를 사용하며, v2.46.0 및 v2.55.0 버전에서와 동일한 바이트 단위의 `/AP` 출력을 생성합니다. `SetFormUnicodeFontDict`를 사용하지 않는 멀티바이트 Tx는 호환성을 위해 v2.46.0 버전의 빈 `/AP` 플레이스홀더 동작을 그대로 유지합니다.
  • 다중 행 + 복합 비 ASCII /AP 지원 및 RTL 양방향 텍스트 모양(UAX #9 + 아랍어 문맥적 결합)은 v2.57.0+ 버전에서 지원하며, v2.56.0 버전에서는 단일 행의 논리적 순서 CJK/키릴 문자/베트남어/그리스어 및 유사한 문자 체계가 지원됩니다.

2026-05-17 Version 2.55.0

  • AcroForm의 서식화된 텍스트 텍스트 상자 위젯 지원이 추가되었습니다 (PDF 1.7 ISO 32000-1 12.7.4.3 + 부록 L). 새로운 THPDFPage.AddRichTextField 메서드는 /RV(서식화된 텍스트 XHTML 본문), /DS(CSS와 유사한 기본 스타일), ffRichText 플래그(/Ff 비트 26) 및 판독기가 /RV를 구문 분석하지 않는 경우 사용되는 일반 텍스트 /V + /DV를 포함하는 텍스트 상자를 생성합니다. Acrobat 및 Foxit은 RichText 비트가 켜져 있으면 /RV에서 직접 렌더링하며, 판독기에 설치된 유니코드 글꼴에서 글꼴 대체 항목을 가져와 멀티바이트 콘텐츠(CJK/키릴 문자/아랍어/강조된 라틴 문자)를 HotPDF이 /DR 리소스에 CID 글꼴을 포함하지 않아도 올바르게 표시합니다. HotPDF 자체의 모양 스트림(/AP) 생성기에 CID 글꼴을 포함하는 것은 향후 작업이며, 서식화된 텍스트를 지원하는 뷰어에게는 필요하지 않습니다.
  • /V 및 /RV는 다중 바이트 입력을 자동으로 감지하고 필요한 경우 UTF-16BE 16진 문자열 인코딩(FE FF BOM + 빅 엔디안 코드 단위)으로 전환하며, 이는 기존의 국제 표준 텍스트 필드 추가 기능과 동일한 동작입니다. ASCII 콘텐츠는 바이트 단위로 동일한 출력을 위해 리터럴 PDF 문자열로 유지됩니다.
  • AcroForm 국제 문자 후보 항목에 대한 후속 작업 3가지가 남아 있습니다. (1) CID 폰트의 /DR 리소스 경로를 조정하여 HotPDF에서 생성된 /AP 스트림이 리치 텍스트 엔진에 의존하지 않고도 비 ASCII 문자를 처리하도록 합니다. (2) 아랍어/히브리어 리치 텍스트에 대한 양방향 문자 모양을 구현합니다. (3) /AA /K 키 입력 동작 지원 기능을 개선합니다.

2026-05-17 Version 2.54.0

  • PDF 1.7 및 ISO 32000-1 7.10.2에 따른 함수 유형 0 (샘플링)을 큐빅 스플라인 보간으로 확장했습니다. RegisterSampledFunction에 새로운 선택적 Order 매개변수가 추가되었습니다 (기본값은 1이며, PDF 1.7 표 38에 따라 1 또는 3을 허용). Order = 3은 각 입력 축에 대해 큐빅 보간을 수행하고, Order = 1은 기존의 선형 동작을 그대로 유지하여 v2.52.0 및 v2.53.0 버전을 사용하는 사용자는 표면적인 변화를 감지하지 못합니다.
  • 다중 입력/다중 출력 함수 유형 0 코드 경로에 대한 엔드 투 엔드 회귀 테스트를 추가했습니다. 새로운 테스트에서 2개의 입력과 3개의 출력을 가진 샘플링된 함수를 4x4 그리드에 생성하고, 3차 보간법을 사용하여 테스트합니다. 또한, 이 테스트는 사양의 샘플 순서 규칙("입력 좌표는 첫 번째 입력 차원을 따라 가장 빠르게 증가해야 함")을 검증하며, 16개의 그리드 포인트 x 3 채널 각각을 분석 수식과 비교하여 정확성을 확인합니다.
  • Acrobat, Foxit 및 qpdf는 모두 Order = 3을 지원합니다. 일부 이전 모바일 뷰어는 알 수 없는 Order 값을 만나면 조용히 선형 보간으로 되돌아갑니다. Cubic은 최대 호환성을 유지하기 위해 선택적으로 사용됩니다.

2026-05-17 Version 2.53.0

  • THotPDF.RegisterSeparationLUT(ColorantName, AlternateCS, Samples) 함수가 v2.52.0의 RegisterSampledFunction 기능을 기반으로 추가되었습니다. 이 함수를 사용하면 사용자는 수동으로 Function Type 0 딕셔너리를 구성하지 않고도 (M-튜플) 샘플의 일련 바이트 스트림으로 전체 비선형 틴트 곡선을 표현할 수 있습니다 (PDF 1.7 ISO 32000-1 8.6.6.4 + 7.10.2).
  • 색상 전환이 비선형인 경우 새로운 LUT 변형을 사용하십시오 (PANTONE Hexachrome 스타일의 색조 그라데이션, 감마 보정된 밀도 곡선, 프레스 특성화를 반영하는 수작업 톤 곡선, 전체 ICC 프로필 메커니즘이 없는 sRGB-to-spot 변환 ICC LUT). 선형적인 0에서 최대 강도까지의 그라데이션이 충분한 경우 v2.45.0의 RegisterSeparation을 사용하십시오 (단일 잉크 PANTONE 스팟 색상의 일반적인 경우).
  • 샘플은 8비트 RGB/CMYK/그레이 바이트로 구성되며, 순서는 (c0_0, c1_0, ..., cM-1_0, c0_1, ..., cM-1_S-1)입니다. 여기서 S는 Length(Samples) / M으로 계산된 그리드 포인트 수입니다. S는 최소 2 이상이어야 함수가 보간 범위를 가질 수 있습니다. 기본적으로 그리드 포인트 사이의 선형 보간이 사용됩니다 (PDF 1.7 /Order 1). 이 함수는 THPDFPage.SetFillColorSpace / SetStrokeColorSpace 및 SetFillColor([tint])에서 사용할 수 있는 등록된 색상 공간 이름(Sep1, Sep2, ...)을 반환합니다. 여기서 0 <= tint <= 1입니다.
  • THPDFSeparationParams.TintFunc의 내부 구현을 THPDFDictionaryObject에서 공통 THPDFObject 기반으로 변경했습니다. 이렇게 하면 Function Type 2 (v2.45.0 버전) 또는 Function Type 0 스트림 (v2.53.0 버전)을 모두 사용할 수 있으며, 두 가지 형태 모두 THPDFArrayObject.AddObject를 통해 동일한 방식으로 직간접 참조로 "/Separation" 배열 내에 "N G R"로 직렬화됩니다.

2026-05-17 Version 2.52.0

  • PDF 1.7, ISO 32000-1 7.10.2의 Function Type 0 (Sampled) 등록 기능을 추가했습니다. 샘플링된 함수는 임의의 입력-출력 매핑을 M차원 출력 샘플의 정규 N차원 그리드로 표현하며, 렌더러는 중간 입력을 평가하기 위해 그리드 지점 간에 선형 보간을 수행합니다. ICC 프로필 기능이 과도할 때이지만, 수동으로 조정된 색상 LUT가 필요한 경우 Type 0을 사용하십시오 (ExtGState의 /TransferFunction, /Separation / /DeviceN에 대한 샘플링된 틴트 변환, 선형 Type 2 / 산술 Type 4 경로에서 이미 지원되는 하프톤 임계값 곡선 또는 Function 사전이 필요한 기타 모든 PDF 구성 요소).
  • 새로운 THotPDF.RegisterSampledFunction(Domain, Range, Size, BitsPerSample, Samples) 함수는 간접적인 /FunctionType 0 스트림을 생성하며, 이 스트림은 /Domain (2N), /Range (2M), /Size (N), /BitsPerSample (1, 2, 4, 8, 12, 16, 24 또는 32), /Order 1 (선형 보간)을 포함하고, 또한 압축된 샘플 데이터를 포함합니다. 이 함수는 생성된 간접적인 THPDFStreamObject를 반환하여, 호출자가 이 객체를 Function 딕셔너리가 필요한 곳에 연결할 수 있도록 합니다.
  • Samples 바이트 배열의 길이는 ceil(GridPoints * M * BitsPerSample / 8) 값과 비교하여 유효성을 검사합니다. BitsPerSample은 8, 16, 24 또는 32 비트이며, 이 값들은 바이트 정렬된 빅 엔디안 방식으로 표현됩니다. 서브 바이트 너비(1, 2, 4 또는 12)는 PDF 1.7의 7.10.2 섹션에 정의된 MSB-first 방식으로 패킹되며, 마지막 바이트는 0으로 채워집니다.
  • HPDFRegisterFunctionType3 및 HPDFRegisterFunctionType4를 통해 Type 3 (스티칭) 및 Type 4 (PostScript 계산기) 함수가 v2.18.0 / v2.47.0부터 내부적으로 사용 가능했으며, 이번 릴리스에서는 Type 0 함수도 동일한 수준의 공개 API 지원을 제공합니다.

2026-05-17 Version 2.51.6

  • v2.51.x 버전의 이진 파일 안전성 검사를 완료하며, 마지막으로 남아있던 `TStringList`의 "Source=Target" 양방향 변환 문제를 해결했습니다. 문제는 `FStructRoleMap` (PDF 1.7 ISO 32000-1 14.7.3 /StructTreeRoot /RoleMap)에서 발생했습니다. `AddStructRoleMap`을 통해 등록된 사용자 정의 구조 역할 이름이, CP_ACP=65001인 Windows 환경에서 더 이상 조용히 변경되지 않습니다 ("Beta: Use Unicode UTF-8" 옵션이 활성화된 지역). 저장 방식은 (Source: TBytes; Target: TBytes) 레코드의 동적 배열로 변경되었으며, 삽입/읽기 시에는 바이트를 보존하는 `Move()` 함수가 사용됩니다. 표준 PDF 구조 유형(Document, P, H1..H6, Span, Div 등)은 사양에 따라 ASCII로 정의되어 있으므로, 이전 버전에서는 실제로 문제가 없었습니다. 이 수정 사항은 작성 도구별 Latin-1 역할 이름을 표준 유형에 매핑하는 경우에만 중요합니다.
  • SaveDictionaryObject에서 PDF 이름 #XX 이스케이프 기능을 확장하여 딕셔너리 키에도 적용했습니다 (PDF 1.7 7.3.5). 이전에 딕셔너리 키는 raw 상태로 출력 스트림에 복사되어, 0x80 이상의 모든 바이트가 이스케이프되지 않아 PDF 사양을 준수하지 않는 출력이 생성되었습니다. 이는 AddStructRoleMap을 사용하여 ASCII가 아닌 소스 역할을 가진 경우 발생할 수 있습니다. 바이트 수준의 정리 및 #XX 이스케이프 로직은 이제 SaveNameObject (이름 값) 및 SaveDictionaryObject (딕셔너리 키) 모두에서 호출되는 공유 헬퍼 함수 (_EscapePDFNameBytes)에 구현되어 있습니다. ASCII 키 (HotPDF에서 생성된 딕셔너리의 일반적인 경우)는 동일한 바이트로 이스케이프되므로 기존 파일 및 테스트에는 영향을 미치지 않습니다.
  • 이번 릴리스 이후, v2.51.x 버전의 이진 파일 안전성 기능(PubSec 수신자, DeviceN 색상 이름, PDF 이름 값 생성, PDF 이름 키 생성, 구조 역할 매핑 저장)이 구조적으로 완료되었습니다. 더 이상 HotPDF에 알려진 모든 바이트 블록에서 AnsiString을 통해 UnicodeString으로 변환하는 과정이 없습니다. 34개의 테스트 항목 중 34개가 통과되었고, 27개의 검증 항목 중 27개가 통과되었습니다.

2026-05-17 Version 2.51.5

  • v2.51.4 버전의 이진 파일 안전성 검사를 두 가지 추가 경로에서 계속 진행했습니다. 이 경로는 Windows CP_ACP=65001 ("Beta: 전 세계 언어 지원을 위해 Unicode UTF-8 사용")이 활성화된 호스트에서 비 ASCII 바이트가 조용히 손상될 수 있는 문제를 해결합니다.
  • DeviceN 색상 이름은 이제 THPDFDeviceNParams 내부에 TBytes 유형의 동적 배열로 저장됩니다 (이전에는 UnicodeString 항목의 TStringList로 저장되었습니다). 이전 방식은 모든 잉크 이름에 대해 AnsiString -> UnicodeString -> AnsiString 변환을 수행해야 했으며, UTF-8 ANSI 환경에서는 0x80 이상의 모든 바이트가 3바이트 대체 시퀀스 EF BF BD로 다시 쓰여졌습니다. ASCII만 사용하는 잉크 이름 (PANTONE / Hexachrome 및 "Red" / "Blue" 스타일 이름)은 영향을 받지 않았습니다. 그러나 사용자 정의 ASCII가 아닌 잉크 이름 (예: 비영어 인쇄 워크플로우에서 Latin-1로 음절이 추가된 잉크 이름)은 이 릴리스 전에 조용히 손상되었습니다.
  • PDF 이름 생성 경로(SaveNameObject)가 이제 바이트 안전하고 규격에 부합합니다. 이전 구현에서는 AnsiString(Trim(String(ValObject.Value)))를 호출하여 디스크에 기록되는 모든 PDF 이름에 대해 동일한 파괴적인 왕복 변환을 수행했습니다. 이제 이름은 바이트 비교("char <= 0x20")를 통해 제거되며("char <= 0x20"은 Delphi의 Trim 의미와 일치), 정규 이름 범위 0x21..0x7E 밖에 있는 모든 바이트는 PDF 1.7 ISO 32000-1 7.3.5에 명시된 대로 #XX 이스케이프 시퀀스를 사용하여 출력됩니다. 선행/후행 공백이 없고 임베디드 특수 바이트가 없는 ASCII 이름은 이전과 동일한 비트 단위 출력을 생성하므로 기존 파일 및 테스트에 영향을 미치지 않습니다.
  • 새로운 양방향 검증기(smoke_devicen_binary_safe)는 0xA0 바이트가 포함된 이름을 가진 DeviceN 잉크를 등록하고, 생성된 /Names 배열이 손상된 "#EF#BF#BD" 시퀀스 대신 규격에 맞는 "#A0" 이스케이프 시퀀스를 포함하는지 확인합니다. 이번 릴리스로 v2.51.x 버전의 이진 안전 기능 체인(PubSec 수신자, DeviceN 잉크 이름, 일반적인 PDF 이름 생성)이 완료되었습니다. 33개의 모든 테스트 항목과 26개의 모든 검증기가 통과했습니다.

2026-05-17 Version 2.51.4

  • 공개 키 보안 처리기에서 수신자 봉투 바이트의 숨겨진 손상을 수정했습니다 (PDF 1.7 ISO 32000-1 7.6.5). 호스트 시스템에서 Windows의 "Beta: Use Unicode UTF-8 for worldwide language support" 기능이 활성화된 경우 (CP_ACP=65001), PKCS#7 봉투 데이터 블롭을 TStringList 기반으로 저장하는 이전 방식은 AnsiString을 UnicodeString으로, 다시 AnsiString으로 변환하는 과정을 거치면서 ASCII가 아닌 모든 바이트를 UTF-8 대체 시퀀스 (EF BF BD)로 다시 작성했습니다. 이러한 손상은 SHA-1 파일 키 계산 (알고리즘 9)과 생성된 /Recipients 16진수 문자열 모두에 동일하게 전파되었으므로, 생성된 PDF는 HotPDF 자체의 손상된 키로 여전히 해독될 수 있지만, 다른 PDF 리더는 원래 봉투 바이트에서 동일한 키를 파생할 수 없었습니다. 즉, 암호화된 파일은 사실상 동일한 CP_ACP 설정이 적용된 HotPDF에서만 읽을 수 있었습니다.
  • 수정 사항은 수신자 저장소를 동적 배열인 `TBytes`로 대체하며, 공개 API `AddPubKeyRecipient`의 서명은 동일하게 유지됩니다. 이제 봉투 바이트는 `Move()`를 통해 그대로 복사되며, 더 이상 코드 페이지 변환 과정은 없습니다.
  • /Recipients 항목의 경우, 이제 제공된 인보이스 데이터를 호스트 로케일과 관계없이 정확히 바이트 단위로 복제합니다. Acrobat, Foxit, qpdf 및 기타 PKCS#7을 지원하는 리더는 파일 암호화 키를 복구할 수 있으며, 이는 사양에 정의된 방식입니다.
  • v2.33.0 버전에서 새로운 양방향 검증기(smoke_pubsec_verify)가 추가되었으며, 이후 빌드에서 계속 실패했습니다. v2.51.4 버전에서는 이 문제가 해결되어 "FAIL"에서 "OK"로 변경되었습니다. 이번 릴리스를 통해 v2.51.x 전체 감사 체인(R=5 감사, R=6 사용자 비밀번호 감사, R=6 소유자 비밀번호 K0 수정, PubSec 수신자 바이트 수정)이 완료되었으며, v2.33.0 이후 처음으로 25개의 모든 검증기가 문제 없이 통과했습니다.

2026-05-16 Version 2.51.3

  • AES-256 V=5 R=6 소유자 비밀번호 검증 해시를 수정하여 ISO 32000-2 알고리즘 2.B에 명시된 대로 작동하도록 했습니다. PDF 2.0 해시 알고리즘은 초기 K 값을 SHA-256(비밀번호 || 솔트 || udata)로 정의하며, 소유자 비밀번호 계산 시 udata는 전체 48바이트 크기의 /U 항목입니다. 이전 버전(v2.22.0 ~ v2.51.2)에서는 udata를 반복적인 K1 단계에서만 사용하고 초기 K 값에서는 사용하지 않아, Acrobat/Foxit/qpdf 스타일의 리더에서 소유자 비밀번호 검증 시 오류가 발생했습니다. 사용자 비밀번호 해독은 영향을 받지 않으며, 이는 udata 인수가 비어 있기 때문에 수정 전후로 동일한 결과를 보여줍니다.
  • Acrobat, Foxit 및 qpdf는 이제 HotPDF에서 생성된 R=6 파일에 대한 소유자 암호를 검증합니다. v2.51.3 이전 버전에 생성된 /O[0:32] 및 /OE 값은 사용자 암호 해독을 통해 읽을 수 있지만, 표준을 준수하는 리더를 통해 소유자 암호로 잠금 해제할 수 없습니다. 외부에서 소유자 암호 검증이 필요한 경우, v2.51.3을 사용하여 영향을 받은 R=6 파일을 다시 생성하십시오.
  • /U / /UE / /Perms 항목에서 V=5 및 R=5 값은 v2.51.3 이전 버전의 출력과 동일하며, 수정 사항은 PDF20HashDanceR6 내의 초기 K SHA-256 값에만 적용됩니다. 이 변경 사항은 UEntry가 비어 있지 않을 때만 적용되며, 이는 CreateKeysV5에서 사용되는 소유자 암호 호출 위치입니다.
  • 새로운 양방향 감사 기능(smoke_aes256_r6_owner_verify)은 전처리 및 사양 알고리즘을 통해 /O[0:32] 값을 얻습니다. 이 기능은 생성된 /O[0:32] 값이 사양과 일치하는지 확인하고, 전처리 방식이 더 이상 동일한 출력을 생성하지 않는지 확인합니다.

2026-05-16 Version 2.51.2

  • v2.51.1의 /Perms 감사 범위를 확장하여 V=5 R=6 ("해시 댄스") 표준 보안 처리 경로(ISO 32000-2 7.6.4.3.4 / 알고리즘 2.B)를 포함하도록 했습니다. 새로운 왕복 검증기는 순수 Python으로 구현된 반복적인 SHA-256 / SHA-384 / SHA-512 + AES-128-CBC 혼합기를 재구현하며, 비어 있는 사용자 암호에서 32바이트 파일 암호화 키를 파생시키고, AES-256-ECB로 16바이트의 /Perms 블록을 해독하며, 모든 필드를 암호화 사전 값과 비교합니다 (/P는 little-endian, 0xFF는 채움, 'T' / 'F' 태그, 'a' 'd' 'b' 리터럴). 동작 변경은 없으며, 이번 릴리스는 v2.51.1에 도입된 R=5 잠금 기능과 일치하는 R=6 경로에 대한 회귀 테스트를 수행한 것입니다.

2026-05-16 Version 2.51.1

  • 회귀 테스트 스위트에서 V=5 R=5 표준 보안 처리기의 /P -> /Perms 바인딩을 잠금 처리했습니다. AES-256 암호화 경로는 ISO 32000-1 알고리즘 10에 따라 16바이트의 /Perms 블록을 생성합니다. 바이트 0-3은 32비트 리틀 엔디안 형식으로 /P 값을 포함하고, 바이트 4-7은 0xFF로 채워지고, 바이트 8은 '/EncryptMetadata'를 추적하는 'T' 또는 'F'를 포함하고, 바이트 9-11은 문자 'a', 'd', 'b'를 나타내고, 바이트 12-15는 임의의 값으로 채워집니다. 새로운 양방향 감사 기능은 알고리즘 2.A(SHA-256(pw || U_Key_Salt) -> AES-CBC-decrypt /UE -> 파일 키)를 통해 사용자 암호에서 파일 암호화 키를 파생시키고, AES-256-ECB를 사용하여 /Perms를 해독하고, 모든 필드를 암호화 딕셔너리 값과 비교합니다. 동작 변경은 없으며, 이번 릴리스는 향후 리팩터링으로 인해 규격에서 요구하는 /P <-> /Perms 관계가 예상치 않게 손상되지 않도록 하기 위한 회귀 테스트를 보장하는 것입니다.

2026-05-16 Version 2.51.0

  • 텐서 곱 패치 메시 쉐이딩 지원을 추가했습니다 (PDF 1.3 이상, ISO 32000-1 8.7.4.5.7, 쉐이딩 유형 7). 이는 v2.48의 유형 4 (자유 형식), v2.49의 유형 5 (격자) 및 v2.50의 유형 6 (쿠ーンズ) 이후, 메시 쉐이딩 제품군에서 마지막 항목입니다. 각 텐서 곱 패치는 완전한 4x4 격자의 양방향 베지어 제어점 p[i][j] (12개 경계 + 4개 내부)와 각 모서리마다 하나의 색상을 가지므로, 패치의 경계와 내부 모두에 대한 세밀한 제어가 가능합니다. SVG 메시 그라디언트의 왕복 처리 및 쿠ーンズ 블렌딩 대신 텐서 곱 베지어 표면이 필요한 모든 벡터 아트워크에 유용합니다.
  • 새로운 `THotPDF.RegisterTensorProductPatchMesh(XMin, YMin, XMax, YMax, NumComponents, Patches)` 함수는 `/ShadingType 7`의 이진 스트림을 생성하며, 이 스트림은 `/BitsPerCoordinate`가 16이고, `/BitsPerComponent`와 `/BitsPerFlag`가 모두 8입니다. 이 스트림은 패턴 타입 2로 감싸지고, 일반적인 `SetFillPattern` 또는 `SetStrokePattern` 파이프라인을 통해 사용할 수 있는 패턴 이름(Sh1, Sh2, ...)을 반환합니다.
  • 각 패치는 16개의 제어 포인트(사양의 스트림 순서에 따른 32개의 부동 소수점 값, 즉 X+Y 좌표: p[0][0..3], p[1][3], p[2][3], p[3][3], p[3][2..0], p[2][0], p[1][0], p[1][1], p[1][2], p[2][2], p[2][1])로 구성되며, 그 뒤에는 4개의 코너 색상(p[0][0] / p[0][3] / p[3][3] / p[3][0] 위치에 있는 4 * NumComponents개의 부동 소수점 값)이 있습니다. 스트라이드는 32 + 4 * NumComponents입니다. 생성된 각 패치는 flag = 0 (독립 패치) 플래그를 가집니다.
  • 이번 릴리스를 통해 ISO 32000-1 8.7.4.5 표준의 모든 메쉬 쉐이딩 패밀리(유형 4, 5, 6, 7)가 지원됩니다.

2026-05-16 Version 2.50.0

  • PDF 1.3 이상 (ISO 32000-1 8.7.4.5.6, Shading Type 6)을 지원하는 Coons 패치 메쉬 쉐이딩 기능이 추가되었습니다. 이는 v2.48의 Type 4 (자유 형식) 및 v2.49의 Type 5 (격자) 쉐이딩 이후 세 번째 메쉬 쉐이딩 유형입니다. 각 Coons 패치는 네 개의 3차 베지어 곡선으로 둘러싸여 있으며, 각 꼭짓점에 하나의 색상을 가집니다. 렌더러는 네 개의 가장자리 사이의 Coons 표면을 생성하며, 이를 통해 임의의 곡선 모양을 가진 색상 영역을 만들 수 있습니다. 이는 굽은 경로의 금속 또는 호일 그라데이션, SVG에서 파생된 그라데이션 메쉬, 그리고 원래는 많은 작은 삼각형으로 근사해야 하는 곡선 가장자리를 가진 모든 영역에 유용합니다.
  • 새로운 `THotPDF.RegisterCoonsPatchMesh(XMin, YMin, XMax, YMax, NumComponents, Patches)` 함수는 `/ShadingType 6` 바이너리 스트림을 생성하며, 이 스트림은 `/BitsPerCoordinate 16`, `/BitsPerComponent 8` 및 `/BitsPerFlag 8` 값을 가집니다. 이 스트림은 패턴 타입 2로 감싸지고, 일반적인 `SetFillPattern` 또는 `SetStrokePattern` 파이프라인을 통해 사용할 수 있는 패턴 이름(Sh1, Sh2, ...)을 반환합니다.
  • 패치 평면 배열은 각 패치를 12개의 제어 포인트(24개의 X+Y 부동 소수점 값)로 구성하며, 그 뒤에 4개의 모서리 색상(4 * NumComponents 개의 부동 소수점 값)이 이어집니다. 스트라이드는 24 + 4 * NumComponents 입니다. 12개의 제어 포인트는 시계 방향으로 패치 경계를 따라 c1부터 c12까지 순서대로 배열되며, c1, c4, c7, c10은 네 모서리에 위치하고 나머지 8개는 내부 베지어 핸들입니다. 각 패치는 flag = 0 (독립적인 패치) 플래그를 가지며, 연속 플래그 1/2/3 (엣지 공유)은 이 편리한 오버로드에서는 노출되지 않습니다.
  • 유형 7 (텐서 곱 패치 메시)은 향후 개발될 기능입니다.

2026-05-16 Version 2.49.0

  • 격자 형태의 Gouraud 셰이딩 삼각형 메시 지원을 추가했습니다 (PDF 1.3 이상, ISO 32000-1 8.7.4.5.5, 셰이딩 유형 5). 이는 v2.48.0의 자유 형식 Type 4와 함께 사용됩니다. 소스 데이터가 이미 정규 샘플 그리드에 배열되어 있고, 애플리케이션에서 명시적인 삼각형 토폴로지를 생성하고 싶지 않을 때 사용합니다. 렌더러는 인접한 각 행 쌍을 자동으로 삼각형 스트립으로 변환합니다.
  • 새로운 `THotPDF.RegisterLatticeFormGouraudShading(XMin, YMin, XMax, YMax, NumComponents, VerticesPerRow, Vertices)` 함수는 M행 x N열 격자를 `/BitsPerCoordinate 16`, `/BitsPerComponent 8` 및 `/VerticesPerRow N`을 가진 이진 Shading 스트림으로 패킹합니다. Type 4과 달리, 각 정점마다 플래그 바이트가 없고, Shading 딕셔너리에서 `/BitsPerFlag`가 없습니다. 이 함수는 일반적인 `SetFillPattern` / `SetStrokePattern` 파이프라인을 통해 사용할 수 있는 패턴 이름(Sh1, Sh2, ...)을 반환합니다.
  • Vertices 평면 배열은 행 우선 순서로 정렬되어 있으며, 각 정점은 (X, Y, c0, c1, ..., c_{NumComponents-1}) 값을 갖습니다. 총 정점 수는 VerticesPerRow의 배수여야 하며, 최소 두 개의 행이 있어야 합니다. NumComponents는 1 (DeviceGray), 3 (DeviceRGB) 또는 4 (DeviceCMYK) 값을 허용합니다.
  • Type 6 (Coons 패치) 및 Type 7 (텐서 곱) 메쉬 쉐이딩은 향후 개발될 예정입니다.

2026-05-16 Version 2.48.0

  • 벡터 일러스트레이션의 색상 그라데이션을 위해 기존의 축 또는 방사형 변형보다 더 일반적인 방식으로, Gouraud 셰이딩을 사용하는 자유 형식의 삼각형 메시 지원을 추가했습니다 (PDF 1.3 이상, ISO 32000-1 8.7.4.5.4, Shading Type 4). 이제 각 정점에 색상이 있는 모든 삼각형 표면을 직접 포함할 수 있습니다.
  • 새로운 THotPDF.RegisterFreeFormGouraudShading(XMin, YMin, XMax, YMax, NumComponents, Vertices) 함수는 삼각형 메시를 이진 Shading 스트림으로 패킹하며, 이때 "/BitsPerCoordinate"는 16, "/BitsPerComponent"는 8, "/BitsPerFlag"는 8로 설정됩니다. 이 스트림은 패턴 유형 2로 감싸지고, 일반적인 THPDFPage.SetFillPattern / SetStrokePattern 파이프라인을 통해 사용할 수 있는 패턴 이름(Sh1, Sh2, ...)이 반환됩니다.
  • 정점 평면 배열은 각 정점에 대해 (X, Y, c0, c1, ...) 형식으로 구성되며, 연속된 세 개의 정점은 하나의 독립적인 삼각형을 형성합니다. 출력 좌표/요소는 빅 엔디안 부호 없는 정수로 인코딩되며, `/Decode` 배열은 인코딩된 범위를 사용자 공간의 지정된 경계 상자로 매핑합니다.

2026-05-16 Version 2.47.0

  • DeviceN 색상 공간 지원을 추가했습니다(PDF 1.3 이상, ISO 32000-1 8.6.6.5). Separation 기능을 6가지 색상 인쇄, 금속/형광 잉크 혼합 및 PDF/X 사용자 정의 잉크 워크플로우에 대해 N개의 색상제로 일반화했습니다. 새로운 THotPDF.RegisterDeviceN(ColorantNames, AlternateCS, TintC1Matrix) 함수는 자동으로 생성된 색상 공간 이름(DevN1, DevN2 등)을 반환하며, 이 이름은 [0..1] 범위 내에서 N개의 틴트 연산자를 사용하는 일반적인 SetFillColorSpace + SetFillColor 파이프라인을 구동합니다.
  • 색조 변환은 PostScript 계산 함수 유형 4이며, 제공된 N x M 행렬에 대한 선형 가중 블렌드를 생성합니다. 따라서 특정 색상 지원이 없는 뷰어에서는 각 출력 채널을 색상 성분의 합으로 보간하여 렌더링합니다.
  • ColorantNames는 모든 스팟 잉크 이름을 허용합니다. PDF 1.7의 7.3.5에 따라 기존 이름 작성 경로에서 공백은 #20으로 이스케이프됩니다. 특별한 이름 ""None""은 사용되지 않는 컬러리언트 슬롯을 나타냅니다.
  • AlternateCS는 DeviceGray, DeviceRGB 또는 DeviceCMYK를 허용하며, 다른 값은 예외를 발생시킵니다.

2026-05-15 Version 2.46.0

  • PDF 1.7 및 ISO 32000-1 12.7.4.3에 따라 텍스트 필드에 대한 확장된 AcroForm 모양 스트림 생성(AutoFormAppearances)을 구현했습니다. v2.28.0 버전에서는 모든 텍스트 위젯에 대해 단일 행 리터럴을 생성했지만, 이제 여러 행 및 결합 필드는 자체 AP(Appearance Stream) 레이아웃 경로를 사용합니다.
  • 다중 행 텍스트 필드(ffMultiline 플래그 포함)는 초기 값을 위젯 너비에 맞게 줄 바꿈하고, 포함된 CR/LF/CRLF 구분 기호를 준수하며, 표시되는 행 수에 맞춰 잘라내고, 적절한 Td + T* 다중 행 레이아웃을 /TL 리딩과 함께 생성합니다.
  • (Flags에 ffComb가 포함되고 MaxLen이 0보다 큰) 결합된 텍스트 필드는 각 문자를 자체 너비의 셀로 렌더링하며, 각 글리프에 대해 절대적인 Tm 행렬을 사용하여 Acrobat이 그리는 것과 동일하게 표시합니다.
  • 단일 행 텍스트 필드는 v2.28.0 레이아웃을 바이트 단위로 그대로 유지하므로, 기존 API 호출자는 동작상의 변경 사항을 감지하지 못합니다.

2026-05-14 Version 2.45.0

  • ISO 32000-1 8.6.6.4에 따라, 스팟 컬러 인쇄 워크플로우를 위한 분리 색상 공간 지원이 추가되었습니다. 새로운 `THotPDF.RegisterSeparation(ColorantName, AlternateCS, TintC1)` 함수는 자동으로 생성된 색상 공간 이름(Sep1, Sep2 등)을 반환하며, 이는 `SetFillColorSpace / SetStrokeColorSpace + SetFillColor([tint]) / SetStrokeColor([tint])` 파이프라인을 단일 틴트 값([0..1] 범위)으로 작동시킵니다.
  • AlternateCS는 DeviceGray, DeviceRGB 또는 DeviceCMYK를 허용합니다. TintC1은 최대 강도로 지정된 색상 잉크의 색상을 나타냅니다 (tint = 1.0). 내부적으로 선형 Function Type 2 틴트 변환을 생성하므로, 특정 색상 지원이 없는 뷰어에서도 잉크가 없는 상태 (tint = 0)와 TintC1 (tint = 1) 사이를 부드럽게 보간하여 렌더링합니다.
  • Pantone 및 기타 공백이 포함된 잉크 이름은 그대로 허용됩니다. -HotPDF은 PDF 1.7의 7.3.5에 따라 색상 공간 이름을 기록할 때 이러한 공백을 ""#20"" 시퀀스로 변환합니다.
  • PDF 1.3 이전 버전의 문서에 대한 처리를 `RequirePDFVersion`을 통해 제한하여, 엄격 모드 1.2 또는 이전 버전과의 호환성을 유지합니다.

2026-05-14 Version 2.44.0

  • ISO 32000-1 8.6.5.3에 따른 CIELab 색 공간 지원이 추가되었습니다. 새로운 `THotPDF.RegisterLabColorSpace(Xw, Yw, Zw, aMin, aMax, bMin, bMax)` 함수는 자동으로 생성된 색 공간 이름(Lab1, Lab2 등)을 반환하며, 이는 일반적인 `THPDFPage.SetFillColorSpace / SetStrokeColorSpace + SetFillColor([L, a, b]) / SetStrokeColor([L, a, b])` 파이프라인을 구동합니다.
  • 일반적인 워크플로는 각 조명 조건에 대해 하나의 공간을 등록하는 것입니다 (ICC 인쇄의 경우 D50, sRGB와 동등한 디스플레이의 경우 D65). 그런 다음 L* 값을 [0..100] 범위로, a* 및 b* 값을 선택한 범위 (일반적으로 -128..127)로 설정하여 색상을 적용합니다. PDF 뷰어 (Adobe Acrobat, Foxit, MuPDF, 브라우저 뷰어)는 Lab 값을 디스플레이 RGB로 변환할 때 WhitePoint 값을 준수합니다.
  • PDF 1.3 이전 버전의 문서에 대한 처리를 `RequirePDFVersion`을 통해 제한하여, 엄격 모드 1.2 또는 이전 버전과의 호환성을 유지합니다.

2026-05-14 Version 2.43.1

  • 실제 흑백 이미지에서 기존의 CCITTFaxDecode 인코더를 전체적으로 검증했습니다. 240x120 픽셀의 1비트 이미지(TBitmap)가 세 가지 모드(icCCITT31 G3 1D, icCCITT32 G3 2D, icCCITT42 G4 / T.6) 모두에서 올바르게 인코딩되는지 확인했습니다. 인코딩된 스트림 크기는 예상되는 G3-1D > G3-2D > G4 압축 순서를 따르며, Adobe Acrobat, Foxit, MuPDF에서 경고 없이 디코딩됩니다. 픽셀 샘플링을 통해 모든 세 가지 모드에서 번갈아 나타나는 검은색/흰색 밴드 패턴이 정상적으로 왕복되는지 확인했습니다. 인코더 코드 변경은 없으며, 이번 릴리스에서는 기존의 PDF 1.7 및 ISO 32000-1 7.4.9 지원을 스모크 테스트 스위트에 고정했습니다.

2026-05-14 Version 2.43.0

  • ISO 32000-1 8.6.6.1에 따라, 색상이 없는 전체 페이지 타일 패턴(PaintType=2)을 추가했습니다. 패턴 스트림에는 타일의 기하학적 정보만 포함되어 있으며, 색상은 페이지 콘텐츠 스트림의 `scn` / `SCN` 연산자를 통해 채우기/선 그리기 시점에 적용됩니다.
  • 새로운 THPDFPage 메서드인 SetFillPatternRGB, SetStrokePatternRGB, SetFillPatternGray, SetStrokePatternGray, SetFillPatternCMYK 및 SetStrokePatternCMYK는 등록된 무색 패턴 이름과 함께 음영 구성 요소(DeviceRGB, DeviceGray 또는 DeviceCMYK, 범위는 [0..1])를 사용합니다. 각 호출 시, 해당 [/Pattern /BaseCS] 음영 색상 공간이 페이지의 Resources/ColorSpace 딕셔너리에 자동으로 등록됩니다(처음 사용하는 경우).
  • 기존의 `SetFillPattern` 및 `SetStrokePattern`은 여전히 색상 있는 `PaintType=1` 변형을 지원합니다. 이 경우, 타일 자체에 색상이 포함되어 있으며, 해당 연산자에 의해 색조 구성 요소가 추가되지 않습니다.
  • 두 가지 코드 경로 모두 기존의 `RegisterTilingPattern` 진입점을 공유합니다. `Colored`가 `true`이면 `PaintType`은 1(색상 있음)으로 설정되고, `Colored`가 `false`이면 `PaintType`은 2(색상 없음)으로 설정됩니다.

2026-05-14 Version 2.42.0

  • PDF 1.4 버전의 소프트 마스크 이미지(SMask) 지원이 추가되었습니다. 새로운 `THotPDF.AddImageWithSMask` 메서드는 원본 RGB 데이터와 8비트 알파 채널 데이터를 입력으로 받아, 컬러 이미지 XObject와 DeviceGray 소프트 마스크 XObject를 생성하고, ISO 32000-1 8.9.5.4에 따라 `/SMask` 교차 참조를 설정합니다. 반환된 이미지 인덱스를 기존 `ShowImage` 메서드와 함께 사용하면 되며, 다른 변경 사항은 필요하지 않습니다.
  • THotPDF.AddImageWithSMask32라는 편리한 도우미 함수를 추가했습니다. 이 함수는 32비트 BGRA TBitmap에서 색상 및 알파 채널을 추출하여 알파 채널을 포함하는 PNG 스타일 비트맵을 단일 호출로 PDF에 포함할 수 있도록 합니다.
  • 두 가지 방법 모두 PDF 1.4 이전 버전의 문서에 대해 `RequirePDFVersion`을 통해 거부하며, 이렇게 하면 strict-mode 1.3으로 출력된 결과물이 규정을 준수합니다.

2026-05-14 Version 2.41.0

  • PDF 1.5 객체 스트림 출력을 추가했습니다. `THotPDF.UseObjectStreams`를 true로 설정하고 `UseXRefStream` 및 `SaveToStream` 옵션을 함께 사용하면, 간접 객체(스트림, 암호화 사전 및 트레일러에서 참조하는 카탈로그 및 정보 사전 제외)를 하나 이상의 `/Type /ObjStm` 컨테이너 스트림으로 묶을 수 있습니다.
  • 문서 크기가 큰 PDF 파일에서 파일 크기를 줄입니다 (많은 페이지, 주석, AcroForm 위젯, 구조 트리 요소 또는 선택적 콘텐츠 레이어). 30페이지의 그래픽만 포함된 테스트 파일의 경우, 파일 크기가 14502바이트에서 8488바이트로 줄어들었습니다 (41.5% 감소), 시각적으로는 아무런 변화가 없습니다.
  • 교차 참조 스트림은 이제 유형 2 압축 객체 항목을 생성하며, 여기서 필드 2는 호스트 ObjStm 객체 번호이고 필드 3은 해당 스트림 내의 항목 인덱스입니다. `UseObjectStreams`는 `UseXRefStream`이 꺼져 있거나(텍스트 교차 참조는 유형 2 항목을 인코딩할 수 없음) 버전이 PDF 1.5보다 낮을 때 자동으로 `false`로 설정됩니다.

2026-05-12 Version 2.40.1

  • Windows 10/11 시스템에서 "Beta: Use Unicode UTF-8 for worldwide language support" 지역 옵션이 활성화된 경우, Adobe Acrobat, Foxit, SumatraPDF 및 브라우저 내장 뷰어에서 생성된 PDF 파일의 렌더링 문제를 수정했습니다. 페이지 콘텐츠 스트림에서 더 이상 PDF 리더가 구문 오류로 거부하는 불필요한 UTF-8 BOM 프리앰블이 포함되지 않습니다.

2026-05-11 Version 2.40.0

  • 대규모 CJK 및 여러 FD를 사용하는 OpenType-CFF 글꼴에 대한 CID 키 기반 CFF 글꼴 서브세팅을 추가했습니다. 여기에는 FDArray 및 FDSelect 데이터를 사용하는 Adobe CJK 글꼴이 포함됩니다.
  • CFF 서브루틴 처리 기능을 개선하여, 큰 OpenType-CFF 글꼴을 전체 글꼴 파일 대신 압축된 PDF 서브셋으로 포함할 수 있도록 했습니다.

2026-05-11 Version 2.39.1

  • 향상된 실제 OpenType-CFF 글꼴 호환성, 특히 더 큰 CFF 테이블과 멀티바이트 오프셋을 가진 Adobe MinionPro 스타일 글꼴에 대한 지원이 강화되었습니다.
  • HPDFExtractTTFPostScriptName 기능을 추가하여, 사용자 정의 글꼴 로딩 코드를 사용하는 애플리케이션이 TrueType 및 OpenType-CFF 글꼴 데이터에서 PostScript 이름을 읽을 수 있도록 했습니다.

2026-05-11 Version 2.39.0

  • CFF 폰트에 대한 글로벌 서브루틴 및 로컬 서브루틴 서브세팅 기능을 추가하여, 임베디드 OpenType-CFF 폰트의 크기를 더욱 줄였습니다.
  • 사용된 CFF 서브루틴 바이트코드를 보존하면서, 안전하게 사용되지 않는 항목을 간결한 반환 스텁으로 대체했습니다.

2026-05-11 Version 2.38.0

  • StoreFont에 OpenType-CFF 자동 임베딩 기능을 추가했습니다. 이제 HotPDF는 GDI로 로드된 글꼴이 sfnt 'OTTO' OpenType-CFF 컨테이너인 경우, /FontFile3을 통해 CFF 기반 CID 글꼴을 생성합니다.
  • OpenType-CFF 글꼴을 직접 처리하는 애플리케이션을 위해 HPDFSfntIsOTF, HPDFOTFFindCFFTable 및 HPDFSubsetOTFContainer 도우미 API를 추가했습니다.

2026-05-11 Version 2.37.0

  • Compact Font Format 및 Type 1C 글꼴 페이로드에 대한 HPDFSubsetCFF를 추가하여, 더 작은 크기의 임베디드 CFF 글꼴 프로그램을 사용할 수 있도록 했습니다.
  • CFF 서브세팅 과정에서 원래 글리프 ID를 유지하여 기존 Type0 / Identity-H 텍스트 출력이 호환되도록 했습니다.
  • HotPDF에 데이터를 전달하기 전에 자체 파이프라인을 통해 글꼴을 로드하는 애플리케이션을 위해 CFF 서브세터를 노출했습니다.

2026-05-10 Version 2.36.0

  • THotPDF의 `EnableFontSubsetting` 옵션을 추가하여 TrueType 글꼴의 부분집합 기능을 제공합니다. 이를 통해 문서에 사용된 글리프 집합이 작을 경우, 포함된 글꼴 파일 크기를 90% 이상 줄일 수 있습니다.
  • Identity-H 텍스트의 경우, 원본 글꼴의 글리프 ID를 유지하면서 PDF 표준 서브셋 글꼴 이름을 추가했습니다.
  • 전체 글꼴 임베딩을 기본값으로 유지하여 전체 글꼴 프로그램이 필요한 워크플로우를 지원합니다.

2026-05-10 Version 2.35.1

  • Adobe Acrobat의 "글꼴 캡처" 기능 사용 중 발생하는 충돌 문제를 수정했습니다. 이제 HotPDF는 임베디드 TrueType 데이터 내의 PostScript 글꼴 이름을 사용하여 PDF 글꼴 이름을 매칭합니다.

2026-05-10 Version 2.35.0

  • THotPDF.BeginIncrementalUpdate 및 THotPDF.SaveIncrementalUpdate를 사용하여 점진적인 PDF 업데이트 기능을 추가했습니다. 기존 소스 바이트는 그대로 유지되고, 새로운 PDF 객체가 호환 가능한 방식으로 추가됩니다.
  • THotPDF.MarkDirty 기능이 추가되어, 애플리케이션이 증분 업데이트 중에 변경된 객체를 명시적으로 다시 저장할 수 있습니다.
  • 이전 서명 바이트 범위를 유지하면서 후속 서명 필드 또는 문서 변경 사항을 추가하여 다중 서명 워크플로우를 활성화했습니다.

2026-05-10 Version 2.34.0

  • THPDFPage.SetAnnotationBorderStyle를 통해 솔리드, 대시, 베벨, 인셋 및 밑줄 스타일을 포함한 주석 테두리 스타일을 추가했습니다.
  • 연결된 팝업 주석을 추가했습니다. 이제 새 팝업은 부모 주석을 참조할 수 있으므로, 사용자가 예상하는 댓글 연결을 표시할 수 있습니다.
  • THPDFPage.LastAnnotation이 추가되어 기존 주석 생성 호출을 변경하지 않고도 주석 스타일링 및 팝업 연결을 더 쉽게 할 수 있습니다.

2026-05-10 Version 2.33.0

  • PDF 암호화에 대한 공개 키 보안 핸들러 지원이 추가되었습니다. 이제 문서를 X.509 인증서 수신자를 대상으로 암호화할 수 있으며, 이전에는 공유 비밀번호만 사용할 수 있었습니다.
  • THotPDF.EnablePubKeyEncryption 및 THotPDF.AddPubKeyRecipient을 추가하여 인증서-수신자 암호화 워크플로우를 지원합니다.
  • HPDFCrypt 中添加了纯 Pascal 语言实现的 SHA-1 支持,同时保留了现有的哈希算法。

2026-05-10 Version 2.32.0

  • THPDFPage.SetTransparencyGroup 및 SetTransparencyGroupICC를 사용하여 투명한 PDF 콘텐츠의 예측 가능한 결합을 위한 페이지 수준의 투명도 그룹을 추가했습니다.
  • DeviceGray, DeviceRGB, DeviceCMYK, 그리고 제거된 색상 공간 및 ICC 프로필 투명도 그룹 옵션을 추가했습니다.
  • THPDFPage.ClearTransparencyGroup 기능이 추가되어, 이전에 할당된 페이지 투명도 그룹을 제거할 수 있습니다.

2026-05-09 Version 2.31.0

  • AcroForm 버튼에 대한 인터랙티브한 푸시 버튼 기능을 추가했습니다. 이전 버전에서는 HotPDF가 버튼 위젯을 배치할 수 있었지만, 클릭해도 아무런 동작이 수행되지 않았습니다. 이제 버튼을 통해 폼을 제출하고, 필드 값을 초기화하고, JavaScript 스크립트를 실행하거나, URI로 이동할 수 있습니다.
  • SubmitForm 액션은 현재 AcroForm 필드 값을 서버 URL로 전송하여 Adobe Reader 및 Foxit에서 별도의 웹 뷰어가 필요 없는 PDF 기반 데이터 수집 양식을 사용할 수 있도록 합니다.
  • ResetForm 기능은 모든 필드를 기본값으로 초기화하며, 선택적으로 특정 필드 그룹으로 제한할 수 있습니다. JavaScript 및 URI 동작은 v2.26.0에서 도입된 PDF 버전 제한을 따릅니다.
  • 이전 버전에서 `AddPushButtonWithAction`은 버튼 위젯의 시각적 속성만 허용했습니다. 이제는 `AddPushButtonWithAction`을 통해 버튼의 모양과 클릭 동작을 모두 단일 호출로 완전히 제어할 수 있습니다.

2026-05-09 Version 2.30.0

  • THPDFPage.SetPageTransition을 사용하여 전체 화면 PDF 프레젠테이션에 페이지 전환 기능을 추가했습니다.
  • THPDFPage에 SetPageDuration 기능을 추가하여, 프레젠테이션 페이지가 지정된 시간 지연 후 자동으로 다음 페이지로 넘어갈 수 있도록 했습니다.
  • PDF 1.5에서 제공하는 Fly, Push, Cover, Uncover 및 Fade와 같은 전환 스타일을 버전 정보를 고려하여 처리하도록 기능을 추가했습니다.

2026-05-09 Version 2.29.0

  • PDF 1.4 뷰어 설정 페이지의 경계 설정을 완료했습니다. 기존의 PrintArea 및 PrintClip 속성에 더해 ViewArea 및 ViewClip 속성을 추가했습니다.
  • ViewArea는 뷰어가 화면에서 보이는 영역으로 사용할 페이지 박스를 결정합니다 (MediaBox, CropBox, TrimBox, BleedBox 또는 ArtBox). ViewClip은 화면상의 클리핑 경계를 제어하며, 이는 디자인 검토용 PDF에서 중요합니다. 왜냐하면 이 PDF에는 일반 보기에서 표시되지 않아야 하는 여백 및 트리밍 표시가 포함될 수 있기 때문입니다.
  • 이러한 옵션은 특히 미리보기 및 인쇄 미리보기 워크플로우에서 화면에서 보이는 영역과 인쇄 영역이 다를 때 유용합니다. 두 항목 모두 PDF 1.4를 필요로 하며, 이전 버전의 PDF를 사용할 때는 자동으로 제외됩니다.

2026-05-09 Version 2.28.0

  • THotPDF.AutoFormAppearances를 사용하여 선택적으로 AcroForm의 외관 스트림을 생성했습니다. 텍스트 필드, 목록 필드, 버튼, 확인란 및 라디오 버튼이 이제 `/NeedAppearances`를 무시하는 뷰어에서도 안정적으로 렌더링됩니다.
  • 자동 외관이 활성화된 경우, Helvetica 및 ZapfDingbats 글꼴에 대한 기본 AcroForm 리소스를 추가했습니다.
  • 이전 AcroForm 동작을 유지하기 위해 기본적으로 AutoFormAppearances 기능을 비활성화했습니다.

2026-05-09 Version 2.27.0

  • ViewerPreferences 및 PageMode 항목에 대한 PDF 버전 제한을 확장했습니다. 각 설정 값은 이제 해당 최소 PDF 버전을 적용합니다. UseAttachments 및 UseOC는 PDF 1.5를 요구하고, PrintScaling은 PDF 1.6을 요구하며, Duplex, NumCopies 및 PickTrayByPDFSize는 PDF 1.7을 요구합니다.
  • 더 오래된 PDF 버전으로 생성된 문서의 경우, 지원되지 않는 뷰어 설정 항목이 자동으로 생략되어, 엄격한 PDF 프로세서 및 보관 검증기에서 경고가 발생하거나 잘못 해석되는 것을 방지합니다.
  • THotPDF.StrictVersionLock가 활성화되면, PDF 1.3 또는 PDF 1.4 형식으로 출력되는 파일은 최신 뷰어 설정 필드를 포함하지 않으므로, 인쇄 제작 및 장기 보관 워크플로우에 적합한 파일 호환성을 유지합니다.

2026-05-09 Version 2.26.0

  • 여러 오래된 API에 PDF 버전 제한 기능을 추가했습니다. 이전에 대상 문서 버전과 관계없이 기능을 허용했던 API들이 이제는 주석 유형, JavaScript 액션, Type 0 폰트, ToUnicode CMaps 및 Catalog Additional Actions에 대해 문서 버전이 이를 지원하는지 확인한 후 작업을 수행합니다.
  • PDF 1.0 또는 PDF 1.1을 대상으로 하는 문서는 더 새로운 기능이 사용될 때 자동으로 필요한 버전으로 업그레이드됩니다. 이를 통해 호출 코드의 변경 없이도 규격을 위반하는 출력이 생성되는 것을 방지할 수 있습니다.
  • THotPDF.StrictVersionLock이 활성화되면, 문서의 버전을 자동으로 높이는 대신, 버전 업그레이드가 필요한 기능 호출은 거부됩니다. 이를 통해 특정 PDF 버전으로 출력을 생성해야 하는 워크플로우를 지원합니다.
  • 이 버전 확인 기능은 v2.27.0 버전에서 ViewerPreferences 및 PageMode로 확장되었으며, v2.31.0 버전으로 모든 주요 기능 영역을 포괄하게 되었습니다.

2026-05-09 Version 2.25.0

  • PDF 사양에 따라 PDF 사전 출력을 수정하여 Name 키를 대소문자를 구분하여 처리하도록 했습니다. 이전에 관련 이름이 대소문자만 다른 경우(예: ExtGState 사전의 /ca(채우기 알파) 및 /CA(획 알파)) 잘못 병합되어, 한 값이 조용히 삭제되었습니다.
  • 이 수정 사항은 동일한 그래픽 상태에서 채우기 및 스트로크에 대한 개별 알파 값을 사용하는 문서의 올바른 투명도 결합을 복원합니다. Adobe Acrobat, Foxit 및 브라우저 PDF 뷰어는 모두 수정된 결과를 예상대로 렌더링합니다.
  • 공용 사전 쿼리 API는 여전히 대소문자를 구분하지 않으므로, 일관성 없는 키 대소문자를 가진 잘못된 PDF 파일을 읽는 기존 코드는 수정 없이 계속 작동합니다.

2026-05-09 Version 2.24.0

  • v2.4.0 이후에 도입된 기능 API에 대한 PDF 버전 제한을 추가하여 생성된 파일이 선택한 PDF 버전과 호환되도록 지원합니다.
  • THotPDF.StrictVersionLock 기능이 추가되었습니다. 이 기능을 사용하지 않으면 HotPDF는 필요에 따라 문서 버전을 자동으로 높입니다. 이 기능을 사용하면 최신 PDF 기능이 필요한 작업은 거부됩니다.
  • ConfigurePDFVersion 기능이 업데이트되어 XRef 스트림, XMP 메타데이터, 태그가 포함된 PDF 및 AES-256 옵션이 이전 버전의 PDF 파일에 노출되지 않도록 했습니다.

2026-05-09 Version 2.23.0

  • HotPDF을 외부 PKI 및 CMS/PKCS#7 서명 라이브러리와 통합하기 위한 세 단계 디지털 서명 워크플로우를 추가했습니다. 이 워크플로우는 서명 필드 플레이스홀더를 생성하고, 서명할 바이트 범위와 다이제스트를 계산한 다음, 외부 서명 후 완성된 CMS 서명을 주입하는 방식으로 작동합니다.
  • 바이트 범위 전략은 서명된 해시가 서명 컨테이너 외부의 파일 영역을 정확하게 포함하도록 보장하며, 이는 PDF 서명 검증기 및 PAdES 규정 준수 검사기가 요구하는 사항과 일치합니다.
  • 모든 암호화 작업(인증서 체인, CMS 구조, 타임스탬프 토큰)은 호출자의 서명 라이브러리(OpenSSL, Windows CAPI, Bouncy Castle 등)에 위임되며, 이를 통해 HotPDF는 특정 PKI 인프라에 의존하지 않도록 설계되었습니다.
  • 다중 서명 문서를 지원합니다. 각 추가 서명은 점진적인 업데이트로 추가되며, 전체 PDF를 다시 생성하지 않고 이전 서명된 바이트 범위를 유지합니다.

2026-05-09 Version 2.22.0

  • THotPDF을 통해 PDF 2.0 AES-256 V=5 R=6 표준 보안 처리 기능을 추가했습니다. UseAES256R6를 사용하십시오.
  • HPDFCrypt에 순수 Pascal로 구현된 SHA-384 및 SHA-512 기본 함수를 추가했습니다.
  • Acrobat DC 및 PDF/A-4 스타일 암호화 워크플로우에서 사용되는 PDF 2.0 해시-댄스 도우미를 추가했습니다.

2026-05-09 Version 2.21.0

  • 태그가 지정된 PDF 지원을 기본 수준의 표시 기능에서 구조화된 PDF 접근성 트리로 확장했습니다.
  • PDF/UA 검증기가 구조 트리를 탐색할 수 있도록 역할 매핑, 페이지 StructParents 할당 및 ParentTree 출력을 추가했습니다.
  • StructTreeRoot 처리 기능을 개선하여, 이후의 태그가 포함된 PDF 호출이 동일 문서 구조를 업데이트하도록 했습니다.

2026-05-09 Version 2.20.0

  • THotPDFPage.SetUserUnit 및 THotPDFPage.SetTabsOrder를 통해 페이지 수준의 /UserUnit 및 /Tabs 지원을 추가했습니다.
  • THotPDF.RegisterOptionalContentGroup 및 THPDFPage.BeginOptionalContent / EndOptionalContent을 사용하여 선택적 콘텐츠(PDF 레이어)를 추가했습니다.
  • THotPDF.RegisterExtGState 및 THPDFPage.SetGraphicsState를 통해 투명도 알파 및 블렌딩 모드에 대한 ExtGState 도우미 기능을 추가했습니다.

2026-05-09 Version 2.19.0

  • PDF 제작 워크플로우를 위한 CropBox, BleedBox, TrimBox, ArtBox 및 페이지 회전 기능을 추가했습니다.
  • THotPDF에 `AddStructureElement` 기능이 추가되어, 역할, 페이지 링크 및 MCID 참조를 사용하여 태그가 지정된 PDF 구조 트리를 만들 수 있습니다.
  • 반복되는 색상 또는 무색 PDF 패턴 채우기 및 윤곽선에 대한 타일링 패턴 지원을 추가했습니다.

2026-05-09 Version 2.18.0

  • THPDFPage에 DrawInlineImage 기능이 추가되어, 작은 래스터 이미지를 페이지 콘텐츠 스트림에 직접 삽입할 수 있습니다.
  • PDF 렌더링 시 부드러운 음영 및 색상 전환 효과를 위해 다중 정점 축 그래디언트를 추가했습니다.
  • PDF/A, PDF/X 및 색상 관리 출판 워크플로우를 위한 OutputIntents 지원을 추가했습니다.

2026-05-09 Version 2.17.0

  • 더 강력한 보안이 필요한 문서에 대해 AES-256 표준 보안 핸들러(PDF 1.7 확장 레벨 3)를 추가했습니다. AES-256으로 암호화된 PDF 파일은 Adobe Acrobat 9 이상 버전, Foxit Reader, Google Chrome, Apple Preview 및 모든 최신 PDF 뷰어에서 열립니다.
  • 사용자 및 소유자 암호는 Adobe 확장 레벨 3 사양에 따라 SHA-256 해싱을 사용하여 생성되므로, 별도의 지원 없이도 모든 호환 가능한 PDF 복호화 프로그램에서 작동합니다.
  • 이번 릴리스에서 AES-256 암호화는 선택 사항이며, 기존의 AES-128 방식은 이전 버전의 Acrobat과의 호환성을 유지하기 위해 기본값으로 유지됩니다.
  • 이후 v2.22.0 버전에서는 PDF 2.0 AES-256-R6를 추가했으며, Acrobat DC 및 PDF/A-4 워크플로우에서 최대 보안을 제공하기 위해 키 파생 알고리즘을 개선했습니다.

2026-05-09 Version 2.16.0

  • 멀티미디어, 법률 및 접근성 관련 사용 사례를 위한 6가지 새로운 주석 유형이 추가되었습니다. 여기에는 워터마크(표시 및 인쇄를 위한 스탬프 오버레이), 검열(콘텐츠 제거를 위한 영역 표시), 화면(내장된 비디오 및 오디오), 3D(대화형 U3D 및 PRC 모델 뷰어), 리치 미디어(대화형 미디어 콘텐츠) 및 팝업(부모 주석에 연결된 댓글 버블)이 포함됩니다.
  • 워터마크 주석은 별도의 화면 표시 및 인쇄 설정을 지원하므로, "초안" 또는 "기밀"과 같은 표시가 화면에만 나타나거나, 인쇄물에만 나타나도록 설정할 수 있습니다.
  • 문서 배포 전에 주석을 삭제하여 콘텐츠 영역을 표시합니다. 사용자의 삭제 워크플로우는 최종 삭제를 수행하며, 변경 사항이 적용되기 전까지는 원본 콘텐츠를 그대로 유지합니다.
  • 모든 여섯 가지 주석 유형은 PDF 버전 제한을 포함하며, 따라서 이전 PDF 표준을 대상으로 하는 문서는 자동으로 최신 주석 유형을 제외하고 사양을 준수합니다.

2026-05-09 Version 2.15.0

  • PDF 출력에 사용자 정의 벡터 글리프 정의를 직접 포함할 수 있도록 Type 3 글꼴 지원을 추가했습니다. Type 3 글꼴은 회사 로고, 독점 기호 세트, 지도 아이콘 및 표준 글꼴로 표현할 수 없는 모든 그래픽 표기법에 적합합니다.
  • 각 글리프는 표준 드로잉 연산자를 사용하여 정의된 PDF 콘텐츠 스트림으로, 이를 통해 Type 3 글리프는 외부 폰트 파일 없이도 모든 확대/축소 수준과 인쇄 해상도에서 깨끗하게 스케일링됩니다.
  • 전체 워크플로우는 즉, 글꼴을 등록하고, 개별 글리프를 정의하고, 페이지에서 글꼴을 선택하는 모든 과정은 `RegisterType3Font`, `AddType3Glyph` 및 `SetType3Font`에 의해 처리됩니다.
  • Type 3 글꼴은 Adobe Reader, Foxit 및 모든 표준 규격 준수 PDF 뷰어에서 뷰어 시스템에 글꼴을 설치하지 않고도 올바르게 렌더링됩니다.

2026-05-09 Version 2.14.0

  • 순수 파스칼로 작성된 AES-256 및 SHA-256 구현을 내부 암호화 기본 요소로 추가하여 문서 보안을 강화했습니다. 이러한 알고리즘은 PDF 1.7 확장 레벨 3 및 PDF 2.0 암호화 표준에서 요구 사항입니다.
  • 새로운 암호화 코드는 외부 DLL 또는 운영체제에서 제공하는 암호화 라이브러리가 필요 없으며, 이를 통해 HotPDF는 모든 지원되는 Delphi 및 C++Builder 환경 및 Windows 버전에서 자체적으로 실행될 수 있습니다.
  • 이번 릴리스에서 AES-128은 여전히 기본 문서 암호화 형식입니다. 새로운 기능들은 v2.17.0에 추가된 AES-256 보안 처리기와 v2.22.0의 PDF 2.0 처리기를 지원합니다.

2026-05-09 Version 2.13.0

  • PDF 벡터 드로잉에 부드러운 축(선형) 및 방사형 그라데이션 채우기가 추가되었습니다. 벡터 그라데이션은 래스터화된 방식보다 훨씬 작은 PDF 파일을 생성하며, 어떤 확대/축소 수준이나 인쇄 해상도에서도 선명도를 유지합니다.
  • 두 가지 그래디언트 유형 모두 DeviceGray, DeviceRGB 및 DeviceCMYK 색 공간을 지원하며, 이는 화면 표시, RGB 인쇄 및 4색 CMYK 생산 워크플로우를 포괄합니다.
  • 어떤 페이지 경로에도 그라디언트를 적용하여 채우기 또는 윤곽선으로 사용할 수 있으며, Adobe Reader, Foxit, SumatraPDF 및 모든 최신 PDF 뷰어에서 올바르게 렌더링됩니다.

2026-05-09 Version 2.12.0

  • THPDFPage.AddSignatureField를 사용하여 서명이 없는 서명 필드 위젯을 추가했습니다. 생성된 PDF에는 시각적 서명 자리 표시자가 포함되어 있으며, 외부 PKI 워크플로, 서명 포털 및 CMS/PKCS#7 서명 라이브러리가 실제 암호화 서명으로 채울 수 있습니다.
  • AcroForm 서명 플래그는 최소 하나의 서명 필드가 있을 때 자동으로 설정되며, 추가적인 API 호출 없이 문서 사양을 준수합니다.
  • Adobe Acrobat, Foxit 및 기타 PDF 서명 솔루션에서 서명 가능한 서명 필드 위젯으로 인식됩니다. 전체 바이트 범위 서명 워크플로우는 v2.23.0에서 확인하십시오.

2026-05-09 Version 2.11.0

  • PDF/UA 및 최신 접근성 표준에서 요구하는 태그 기반 PDF 인프라를 추가했습니다. 태그가 포함된 문서는 스크린 리더, 보조 기술 및 텍스트 추출 도구가 따를 수 있는 논리적인 읽기 순서와 의미 구조를 갖습니다.
  • THotPDF.EnableTaggedPDF은 문서 구조 트리를 활성화하고, THotPDF.Lang은 문서의 기본 언어를 설정합니다. 이 두 기능은 접근성 규격 준수를 위한 검사기에 필수적입니다.
  • 마크업 콘텐츠 연산자는 페이지의 개별적인 그리기 작업을 의미론적 역할(단락, 제목, 그림 등)과 식별자를 사용하여 태그할 수 있도록 하여, 생성된 PDF 파일에서 올바른 리플로우 및 화면 판독기 추출을 가능하게 합니다.
  • 페이지 및 문서별로 구조 요소 및 마크된 콘텐츠 식별자를 추적하며, 이는 다페이지 태그 문서에 대한 PDF 사양과 일관됩니다.

2026-05-09 Version 2.10.0

  • FlateDecode 이미지 스트림에 대한 PNG 예측 및 TIFF 수평 차이 예측 지원을 추가했습니다. 예측기는 압축 전에 각 행에 대한 적응형 필터링을 적용하여 사진 및 부드러운 그라데이션 이미지의 출력 크기를 크게 줄입니다.
  • PNG 최적 예측(적응형 행 모드) 및 TIFF 예측기 2(수평 차분)는 사용자 정의 이미지 임베딩 파이프라인을 위한 독립적인 인코딩 도우미로 제공됩니다.
  • 두 예측기 모두 DeviceGray, DeviceRGB 및 DeviceCMYK 이미지 데이터를 지원하며, 화면 표시 및 4색 인쇄 워크플로우를 지원합니다.

2026-05-09 Version 2.9.0

  • 기존 문서 정보 딕셔너리와 함께 XMP 메타데이터 스트림 출력을 추가했습니다. XMP는 임베디드 PDF 메타데이터의 최신 표준이며, PDF/A, PDF/X 및 많은 보관 워크플로우에 필요합니다.
  • 데스크톱 검색 엔진, 디지털 자산 관리 시스템 및 더 이상 이전 Info 딕셔너리를 참조하지 않는 PDF 처리 파이프라인에서 XMP에 포함된 메타데이터가 읽힙니다.
  • XMP 스트림은 출력 파일에서 압축되지 않은 상태로 유지되므로, 외부 도구 및 명령줄 유틸리티를 사용하여 파일을 디코딩하지 않고도 메타데이터를 검사할 수 있습니다.
  • 정확한 메타데이터 내용을 요구하는 애플리케이션은 THotPDF.CustomXMP를 통해 완전히 사용자 정의된 UTF-8 XMP 패킷을 제공하여 자동 생성을 우회할 수 있습니다.
  • 문서 암호화가 활성화되면, XMP 스트림은 기본적으로 문서의 나머지 부분과 함께 암호화되어 메타데이터의 기밀성을 유지합니다.

2026-05-09 Version 2.8.0

  • PDF 1.5의 선택적 교차 참조 스트림 출력을 추가했습니다. 교차 참조 스트림은 기존의 xref 테이블에서 사용되는 큰 텍스트 섹션 대신, 객체 오프셋 테이블을 압축된 이진 형식으로 인코딩하여 모든 문서의 파일 크기를 줄입니다.
  • PDF 1.5 버전의 기능, 예를 들어 객체 스트림(v2.41.0에 도입)을 사용하려면 상호 참조 스트림이 필요하며, 문서가 1.5보다 낮은 PDF 버전을 대상으로 하는 경우 자동으로 비활성화됩니다.
  • 최신 뷰어, 보관 도구 및 PDF/A 검증기에서 교차 참조 스트림이 있는 PDF 파일을 더욱 효율적으로 처리합니다.
  • 기존의 텍스트 xref 테이블은 기본값으로 유지되며, 이는 기존 PDF 리더 및 엄격한 프로세서와의 호환성을 유지합니다.

2026-05-09 Version 2.7.0

  • 인쇄 및 PDF/X 워크플로우를 위한 네이티브 DeviceCMYK 색상 출력을 추가했습니다.
  • THotPDF.RegisterICCProfile를 사용하여 ICC 기반 색상 공간 등록 기능을 추가했습니다.
  • ICC 프로필 및 임의 구성 요소 색상 값에 대한 일반적인 채우기 및 윤곽선 색상 공간 API를 추가했습니다.

2026-05-09 Version 2.6.0

  • 텍스트에 하이라이트, 밑줄, 물결선 및 취소선 텍스트 주석 기능을 추가했습니다.
  • 다각형, 폴리라인, 잉크 및 캐럿 주석을 추가했습니다.
  • 문서 내, 문서 간, 외부 파일 탐색을 위한 GoTo, GoToR 및 Launch 링크 기능을 추가했습니다.

2026-05-09 Version 2.5.0

  • 텍스트 필드, 체크박스, 라디오 버튼, 콤보 박스, 목록 상자 및 푸시 버튼에 대한 AcroForm 지원을 추가했습니다.
  • THPDFFormFieldFlags가 추가되어, 애플리케이션이 수동으로 비트 조작을 수행하지 않고도 일반적인 폼 필드 옵션을 구성할 수 있습니다.
  • 생성된 양식은 이제 `/NeedAppearances`를 설정하여 일반적인 PDF 뷰어가 필드를 자동으로 렌더링할 수 있도록 합니다.

2026-05-08 Version 2.4.0

  • AES-128 PDF 암호화 문제를 수정했습니다. 문자열과 스트림이 이제 실제로 AES-CBC를 사용하여 V=4 / R=4 보안 수준으로 암호화됩니다.
  • CryptKeyLength=aes128 이제 암호화된 PDF 파일을 생성하며, 설정된 사용자 또는 소유자 암호를 사용하여 호환 가능한 뷰어가 해당 파일을 열 수 있습니다.
  • ASCIIHexDecode, ASCII85Decode 및 RunLengthDecode 인코더 도우미를 추가했습니다.
  • 번들 JBIG2 및 JPEG 2000 라이브러리를 업데이트하여, 지원되지 않는 디코딩 시 더미 이미지 데이터를 반환하는 대신, 이를 명확하게 보고하도록 했습니다.

2026-05-06 Version 2.3.23

  • 현재 RAD Studio 및 Visual Studio 도구 체인에 대한 번들 zlib-ng, libjpeg-turbo 및 libtiff 객체 빌드를 최적화했습니다.
  • Delphi 및 C++Builder 환경에서 네이티브 압축 및 이미지 라이브러리에 대한 힙 정렬을 개선했습니다.
  • Delphi 및 C++Builder 자동 회귀 테스트를 Win32, Win64 및 Win64x 환경에서 검증했습니다.

2026-05-05 Version 2.3.22

  • 번들 64비트 Flate 압축 빌드에서 zlib-ng 런타임 SIMD 디스패치를 활성화했습니다.
  • Win32 zlib-ng는 기존 도구 체인과의 호환성을 유지하기 위해 안정적인 일반 객체 경로에 그대로 유지되었습니다.
  • 컴파일 성공이지만 출력 객체가 없는 네이티브 객체 빌드는 빌드 실패로 처리됩니다.

2026-05-05 Version 2.3.21

  • 번들 Win32, Win64 및 Win64x 객체 빌드에서 libjpeg-turbo의 SIMD 가속을 활성화했습니다.
  • THotPDF 빌드 플래그를 통해 SIMD 지원을 명시적으로 구현했습니다.
  • Delphi Win32에서 SIMD JPEG 객체 세트의 링크를 방해하는 Win32 NASM OMF 출력 문제를 수정했습니다.
  • SIMD 및 zlib-ng 재빌드 후 발생한 Win64 TIFF 이미지 관련 문제를 수정했습니다.

2026-05-05 Version 2.3.20

  • 페이지 스트림, 글꼴, CMaps, 이미지, TIFF 출력 및 FlateDecode 지원에 사용되는 내장 Flate 백엔드를 zlib-ng로 대체했으며, zlib과 호환되는 모드로 작동하도록 설정했습니다.
  • zlib-ng 마이그레이션 과정에서 발견된 압축 스트림 문제와 TIFF 형식의 작은 이미지 가져오기 문제를 해결했습니다.
  • JPEG 워크플로우는 libjpeg-turbo를 기반으로, TIFF 워크플로우는 libtiff를 기반으로 유지되었습니다.
  • 델파이 및 C++빌더 PDF 생성, 이미지 가져오기, 압축, 암호화, 하이퍼링크, 페이지 설정 및 복사/병합/편집 워크플로우에 대한 광범위한 자동 회귀 테스트를 추가했습니다.

2026-05-01 Version 2.3.19

  • Win64 환경에서 FlateDecode 페이지 스트림 생성 시, 밀집 바코드 출력 문제를 해결했습니다.
  • 최신 Delphi 페이지 및 글꼴 스트림 압축을 안정적인 RTL zlib 경로와 일치하도록 조정했습니다.

2026-05-01 Version 2.3.18

  • C++Builder Win64x 환경에서 암호화된 PDF 생성 시, 포인터 크기 RC4 키 설정 오류를 수정했습니다.
  • C++Builder Win64x 빌드에서 TIFF 가져오기 문제를 수정했습니다.
  • LoadFromFile을 사용하여 열린 PDF 파일의 페이지 추가 기능을 수정하여, 추가된 페이지가 안전한 객체 번호로 저장되도록 했습니다.

2026-05-01 Version 2.3.17

  • C++Builder의 CanvasDrawing 및 GraphicDraw 데모를 개선된 Delphi 그래픽 샘플과 일치하도록 업데이트했습니다.
  • C++Builder 데모 버전의 뷰어 기본 설정 기능을 개선하여 사용자 인터페이스 상태를 명확하게 하고, 유효성 검사 기능을 추가했으며, 미리 설정된 값을 저장하고 불러오는 기능을 지원하고, 방향 설정 기능을 위한 별도 출력을 제공합니다.

2026-05-01 Version 2.3.16

  • 병합된 PDF 파일에서 CID TrueType 글꼴과 중첩된 너비 배열이 포함된 경우 페이지 복사 문제를 해결했습니다.
  • 여러 PDF 문서에서 페이지를 순차적으로 복사할 때 객체 매핑 기능을 개선했습니다.

2026-05-01 Version 2.3.15

  • Delphi 데모 버전의 뷰어 기본 설정 기능을 개선하여, 관련 옵션에 대한 제어 기능만 활성화되도록 했습니다.
  • 뷰어 기본 설정 오류 보고, 복사-개수 검증 기능 추가 및 명명된 사전 설정 저장/로드 기능을 지원합니다.

2026-05-01 Version 2.3.14

  • PDFmerge Delphi 데모를 자체적으로 실행 가능한 병합 샘플로 재작업했으며, 필요한 경우 원본 PDF 파일을 생성합니다.
  • 병합 유효성 검사, 출력 인덱싱 및 UI 성공/실패 메시지를 개선했습니다.

2026-05-01 Version 2.3.13

  • Delphi용 CanvasDraw 및 GraphicDraw 데모를 개선하여 더욱 명확하고 재현 가능한 시각적 결과를 얻을 수 있도록 했습니다.
  • GDI 글꼴 경로에서 TrueType 글꼴 선택 기능을 개선하여, 래스터 글꼴로 대체될 때 발생하는 임베딩 실패를 줄였습니다.
  • PDF에서 동일한 글꼴이 여러 텍스트 영역에 사용될 때 문자 간 간격 문제를 수정했습니다.
  • 요청된 글꼴 이름과 문자 집합을 포함하여 글꼴 임베딩 오류 메시지를 개선했습니다.

2026-05-01 Version 2.3.12

  • CopyPage 데모를 개선하여 별도의 도구가 필요 없이 표준이 아닌 /Pages 트리를 가진 PDF 파일을 복사할 수 있도록 했습니다.
  • CopyPage 이제 어떤 복사 경로가 성공하든 상관없이 FlateDecode로 압축된 출력을 생성합니다.
  • CopyPageFixed 독립 샘플을 메인 CopyPage 데모에 통합했습니다.

2026-05-01 Version 2.3.11

  • 생성된 PDF 파일은 이제 기본적으로 각 페이지가 창 높이에 맞춰 표시되도록 열립니다.
  • 사무용, 대형 포맷, 드로잉, 카드, 신분증, 사진, 일본어, 중국어 및 대만 용지 크기에 대한 많은 기본 페이지 크기 이름을 추가했으며, 기존의 "ps-" 접두사가 붙은 이름과의 호환성을 유지했습니다.
  • 델파이 페이지 크기 데모를 LargeSize, NormalSize 및 SmallSize 프로젝트로 재구성했습니다.

2026-04-29 Version 2.3.10

  • TIFF 호환성 레이어에서 RAD Studio XE7 패키지 빌드 문제를 수정했습니다.
  • RAD Studio 10 Seattle 및 10.1 Berlin 버전에서 발생하는 경고 수를 줄였습니다.
  • RAD Studio 제품 버전 9.0부터 12.0까지의 명령줄 라이브러리 빌드 매핑 오류를 수정했습니다.
  • RAD Studio ProductVersion 9.0용 명령줄 패키지 빌드를 복원했습니다.
  • RAD Studio XE2 Win64 빌드 문제를 해결하기 위해, Win64 호환성 스텁에서 요구하는 CRT vsnprintf 심볼을 선언했습니다.
  • 더 이상 버전 번호가 필요하지 않습니다.

2026-04-29 Version 2.3.9

  • RAD Studio 10.1 Berlin 라이브러리 패키지 빌드 문제를 해결하기 위해, Lib 디렉토리에서 패키지를 컴파일하도록 수정했습니다.
  • 이전 Delphi 컴파일러에서 Trial 라이브러리 빌드를 수정하여, Trial 워터마크 경로에서 인라인 변수 선언을 제거했습니다.

2026-04-29 Version 2.3.8

  • RAD Studio 10.3 Rio 빌드에서 TIFF 스트림 콜백 경로에서 더 이상 사용되지 않는 `TStream.Seek` 컴파일러 경고를 제거했습니다.

2026-04-29 Version 2.3.7

  • 번들 libtiff 4.7.x 객체 파일을 사용할 때 TIFF에서 PDF로 변환하는 과정에서 발생하던 문제를 해결했습니다.
  • 묶음 zlib Pascal 브리지의 RAD Studio Win32 컴파일 문제를 더 엄격한 컴파일러 설정에서 해결했습니다.
  • TIFF에서 PDF로 변환하는 기능에 대한 DUnitX 회귀 테스트를 추가했습니다.

2026-04-28 Version 2.3.5

  • 번들 zlib, libjpeg-turbo 및 libtiff 라이브러리의 소스 패키지 재빌드 문제를 해결했으며, 이를 위해 기존의 Borland C++ Win32 컴파일러를 사용했습니다.
  • 더 안정적인 Delphi 및 C++Builder 빌드를 위해 배포된 Win32 및 Win64 타사 객체 파일을 재구성하고 정렬했습니다.
  • 공개 API 변경 사항은 없습니다. 기존 Delphi, C++Builder 및 RAD Studio 프로젝트는 이 버전을 호환성을 유지하기 위해 사용할 수 있습니다.

2026-04-19 Version 2.3.3

  • RAD Studio 프로젝트의 안정성을 향상시켜 HotPDF 리소스 컴파일에 영향을 미치는 호스트 INCLUDE 환경 설정 문제를 해결했습니다.
  • 패키지 빌드 시 중복 리소스 경고를 줄였습니다. 특히 RAD Studio 13.1 Florence 프로젝트에서 이러한 현상이 많이 발생했습니다.

2026-04-19 Version 2.3.2

  • 패키지 및 데모 프로젝트 출력 폴더가 이제 활성 RAD Studio 버전에 따라 자동으로 설정됩니다.
  • THotPDF370 패키지 빌드 동작을 개선하여 새로 생성된 리소스와 함께 이전 버전의 리소스 파일이 연결되는 문제를 방지했습니다.

2026-04-19 Version 2.3.1

  • C++Builder의 TextOut 데모가 이제 수동 편집 없이도 지원되는 RAD Studio 버전에서 빌드됩니다.
  • TextOut 데모의 Win64x 빌드 동작 문제를 수정하여, 필요한 리소스 파일이 링크 전에 준비되도록 했습니다.

2026-04-19 Version 2.3.0

  • Win32, Win64 및 Win64x 타겟에 대한 C++Builder 13.1 Florence 지원을 완전히 추가했습니다.
  • Delphi 및 C++Builder에서 `TextOut` 함수의 기능을 표준화하고, 기존 C++Builder에서 사용하던 함수 이름과의 호환성을 유지했습니다.
  • Delphi Win64의 정적 링크 문제를 해결하기 위해, 번들된 zlib, libjpeg-turbo 및 libtiff 객체 파일에서 이전 링커 경고를 제거했습니다.
  • C++Builder 프로젝트에서 생성된 HotPDF 라이브러리를 일반 RAD Studio 검색 경로를 통해 찾을 수 있도록 Win64x 패키지 출력을 개선했습니다.

2026-04-17 Version 2.2.1

  • 번들된 타사 압축 및 이미지 라이브러리에서 발생하는 Delphi Win32 링커 경고를 제거했습니다.
  • 델파이 및 C++ 빌더 환경에서 zlib, JPEG 및 TIFF 지원에 대한 정적 링크 호환성을 개선했습니다.

2026-04-14 Version 2.2.0

  • 번들된 타사 라이브러리를 zlib 1.3.2, libjpeg-turbo 3.1.90 및 libtiff 4.7.1로 업그레이드했습니다.
  • 업데이트된 압축, JPEG 및 TIFF 라이브러리를 위한 Win32 및 Win64 정적 링크를 현대화했습니다.
  • JPEG 또는 TIFF 입력을 사용하는 PDF 생성 시나리오에서 이미지 형식 호환성을 확장했습니다.
  • 현재 HotPDF API, 예제 및 라이브러리 구조와 일치하도록 HTML 도움말을 업데이트했습니다.

2026-04-13 Version 2.1.4

  • RAD Studio XE2부터 XE8까지의 Win64 컴파일 문제를 해결했습니다.
  • 더 오래된 Delphi 컴파일러에서 사용되는 번들 객체 파일과의 호환성을 향상했습니다.
  • 중복 리소스 링크 경고를 유발할 수 있는 오래된 패키지 리소스 파일을 제거했습니다.
  • HotPDF 패키지에 대한 Delphi XE3 프로젝트 메타데이터를 수정했습니다.

2026-04-12 Version 2.1.3

  • Delphi TestNumeric 데모를 확장하여 숫자 PDF 출력에 대한 실용적인 회귀 테스트로 만들었습니다.
  • 소수, 분수, 정수에 대한 검증 범위를 확대하고, PDF 다시 로드 동작을 개선했습니다.
  • 디버그 출력 파일을 선택적으로 활성화할 수 있도록, 전용 컴파일 타임 스위치를 추가했습니다.
  • 디버그 로깅 및 숫자 출력 테스트에 대한 도움말 내용을 업데이트했습니다.

2026-04-10 Version 2.1.2

  • Win32 및 Win64 PDF 출력에서 포함된 글꼴 렌더링이 개선되었습니다.
  • 내장 글꼴 간 전환 시 발생하는 불완전한 글리프 렌더링 문제를 수정했습니다. 여기에는 Calibri와 같은 일반적인 Windows 글꼴이 포함됩니다.
  • 폰트 테스트 데모를 업데이트하고, 시각적 확인을 용이하게 하기 위해 샘플 PDF 파일을 생성했습니다.
  • 글꼴 임베딩, 유니코드 텍스트 출력 및 임베디드 글꼴 예제에 대한 HTML 도움말 페이지를 업데이트했습니다.

2026-04-08 Version 2.1.1

  • Delphi 및 C++Builder용 ViewerPreferences 데모를 업데이트하여 현재 HotPDF API와 일치하도록 했습니다.
  • 최신 PDF 뷰어 설정 옵션에 대한 지원이 추가되었습니다.
  • UI에서 선택한 뷰어 기본 설정에 따라 생성된 데모 출력 결과를 개선했습니다.
  • ViewerPreferences 및 관련 문서 속성에 대한 HTML 도움말 페이지를 업데이트했습니다.