From 5874e5205572cc3a6d54a1f25bac1ff2d48299ff Mon Sep 17 00:00:00 2001 From: mtlcl410 Date: Thu, 5 Nov 2026 08:11:58 +0800 Subject: [PATCH] M11: PDF/A verify reports a halftone phase (HTP) in a graphics state (6.2.5) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Pq7HyDBXygTf7jcqdsjcfn --- crates/preflight/src/gstate.rs | 6 ++++++ crates/preflight/src/lib.rs | 4 ++++ crates/preflight/src/tests.rs | 1 + 3 files changed, 11 insertions(+) diff --git a/crates/preflight/src/gstate.rs b/crates/preflight/src/gstate.rs index e34b444079..ea0f9e569f 100644 --- a/crates/preflight/src/gstate.rs +++ b/crates/preflight/src/gstate.rs @@ -2,6 +2,7 @@ //! rely on. //! //! - no transfer function: no `/TR` entry, and `/TR2` only as `/Default` (ISO 32000-1 10.4); +//! - no `/HTP` (halftone phase) entry, a PDF 1.2 key ISO 32000-1 no longer defines; //! - halftones of type 1 or 5 only, without a `/HalftoneName` (ISO 32000-1 10.5.5); the halftones //! a type 5 halftone holds for its colorants are checked the same way; //! - a rendering intent (`/RI`) that is one of the four of ISO 32000-1 8.6.5.8, Table 70. @@ -28,6 +29,8 @@ pub(crate) struct Findings { pub(crate) transfer: bool, /// A graphics state has a `/TR2` other than `/Default`. pub(crate) transfer2: bool, + /// A graphics state has an `/HTP`. + pub(crate) phase: bool, /// Halftone types other than 1 and 5, in order. pub(crate) halftone_types: BTreeSet, /// A halftone has a `/HalftoneName`. @@ -96,6 +99,9 @@ impl Scan<'_> { if present(b"TR2").is_some_and(|f| f.as_name() != Some(b"Default")) { self.findings.transfer2 = true; } + if present(b"HTP").is_some() { + self.findings.phase = true; + } if let Some(ht) = present(b"HT") && let Some(ht) = ht.as_dict() { diff --git a/crates/preflight/src/lib.rs b/crates/preflight/src/lib.rs index 10bbfca8a9..3886a5181a 100644 --- a/crates/preflight/src/lib.rs +++ b/crates/preflight/src/lib.rs @@ -124,6 +124,7 @@ pub const WORDINGS: &[&str] = &[ "The document has document-level JavaScript", "A graphics state has a transfer function (TR)", "A graphics state has a transfer function (TR2) other than Default", + "A graphics state has a halftone phase (HTP)", "A halftone has type {}: only types 1 and 5 are allowed", "A halftone has a HalftoneName", "A graphics state has the rendering intent {}, which isn't a standard one", @@ -529,6 +530,9 @@ pub fn verify(doc: &Document, level: Level) -> Vec { if gs.transfer2 { issue("6.2.5", "A graphics state has a transfer function (TR2) other than Default", None, None, false); } + if gs.phase { + issue("6.2.5", "A graphics state has a halftone phase (HTP)", None, None, false); + } for kind in gs.halftone_types { issue("6.2.5", "A halftone has type {}: only types 1 and 5 are allowed", Some(kind.to_string()), None, false); } diff --git a/crates/preflight/src/tests.rs b/crates/preflight/src/tests.rs index 3285ebc35f..b35f490157 100644 --- a/crates/preflight/src/tests.rs +++ b/crates/preflight/src/tests.rs @@ -521,6 +521,7 @@ fn extended_graphics_states_are_checked() { assert_eq!(gs("/A 6 0 R"), [tr]); assert_eq!(gs("/A << /TR2 4 0 R >>"), [tr2]); assert_eq!(gs("/A << /TR2 /Identity >>"), [tr2]); + assert_eq!(gs("/A << /HTP [0 1] >>"), ["A graphics state has a halftone phase (HTP)"]); // Halftones: the type, also of a type 5 halftone's colorants and of a stream, and the name. assert_eq!(gs("/A << /HT << /HalftoneType 6 >> >>"), ["A halftone has type 6: only types 1 and 5 are allowed"]); assert_eq!(gs("/A << /HT 7 0 R >>"), ["A halftone has type 6: only types 1 and 5 are allowed"]);