From 233bc6c9328e821eb0a267f23e178c8b55f35fc6 Mon Sep 17 00:00:00 2001 From: bflatastic Date: Sun, 8 Nov 2026 21:42:10 +0700 Subject: [PATCH] Ungroup keeps the translucency an unmatched Q doesn't restore A Q with no q before it restores nothing; the renderer ignores it. The check for translucency at the Do took it as restoring the opaque default, so a transparency group drawn after /H gs Q was inlined although it is drawn translucent. --- crates/edit/src/tests.rs | 2 ++ crates/edit/src/ungroup.rs | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/edit/src/tests.rs b/crates/edit/src/tests.rs index 934153a321..a10ace0ae1 100644 --- a/crates/edit/src/tests.rs +++ b/crates/edit/src/tests.rs @@ -5041,6 +5041,8 @@ fn ungroup_refuses_what_would_draw_differently() { ungroup(&[("Group", group(&[]))], fill, "/H gs /One gs", half()).unwrap(); // The translucency ends with its q … Q scope. ungroup(&[("Group", group(&[]))], fill, "q /H gs Q", half()).unwrap(); + // A Q with no q to restore is ignored, as the renderer ignores it: the translucency stays. + refused(ungroup(&[("Group", group(&[]))], fill, "/H gs Q", half()), "translucent"); // Without a group, translucency at the Do applies to each part just as it would inline. ungroup(&[], fill, "/H gs", half()).unwrap(); ungroup(&[("Group", group(&[]))], fill, "", None).unwrap(); diff --git a/crates/edit/src/ungroup.rs b/crates/edit/src/ungroup.rs index 73c255f747..ed7ba908a7 100644 --- a/crates/edit/src/ungroup.rs +++ b/crates/edit/src/ungroup.rs @@ -691,7 +691,8 @@ pub(crate) fn translucent_at(doc: &Document, resources: &Dict, ops: &[Op], at: u for op in ops.iter().take(at) { match op.op.as_slice() { b"q" => stack.push(now), - b"Q" => now = stack.pop().unwrap_or([false; 4]), + // A Q with nothing to restore is ignored, as renderers ignore it. + b"Q" => now = stack.pop().unwrap_or(now), b"gs" => { let Ok(Some((_, i))) = resource_operand(op) else { continue }; let Some(gs) = op.name(i).and_then(|n| states.get(n)).map(|g| doc.resolve(g)).and_then(|g| g.as_dict().cloned()) else {