Commit Graph
3 Commits
Author SHA1 Message Date
alehelandClaude Opus 5.5 e71a946c0f fix(edit): a backdrop is only a fill the graphics state paints plain white
Review of #2815 (FredApps): two ways the detector took real content for a
page's own white backdrop and replaced it by default.

- A `gs` sets only the keys its dictionary has, but each one replaced the
  whole opacity decision and read every key it left out as its default,
  so `/Transparent gs /LineOnly gs 1 g ... re f` (ca 0.5, then only a
  line width) counted as opaque. Fill alpha, soft mask and blend mode are
  now kept one by one, through `gs` and `q`/`Q`.
- A transfer function was never read: TR or TR2 mapping 1 to 0 paints
  `1 g` black, and the fill was still replaced. The transfer function is
  tracked too, TR2 over TR in the same dictionary, and only /Identity
  (and /Default for TR2) counts; anything else leaves the fill alone.

Tests: nine graphics states that must keep the fill (each also checks Add
Background leaves the content as it was) and nine that still find the
backdrop (keys set back, TR2 /Default over a TR function, q/Q restoring),
plus an end-to-end render of the reviewer's translucent case under a red
background. All the keep cases fail on the code before this change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 08:31:05 +01:00
alehelandClaude Opus 5.5 3485e92a95 fix(edit): backdrop copies keep no reference that outlives a redaction
The tag on a page's backdrop copy, `/PCBackdrop << /Original ref /At /Len >>`, kept the
page's original content stream reachable. After Add background, then Redact (or Remove
Hidden Information, or Edit text) and a full save, the text taken off the page was still in
the file, in the original stream the tag pointed at. Text extraction didn't show it; reading
the file's bytes did. Restore also gave up after any edit, so the fill stayed off without a
word.

The tag is now `/PCBackdrop << /Index n /Op (f) /Before <SHA-256> /Was [num gen] >>`: how many
of the copy's operators come before the `n`, the fill it stands in for, a hash of those
operators by value (redaction writes the stream out again with other spacing), and the
original's number as two integers, which keep nothing alive.

Remove background turns the fill back on in the copy when the operators before it still
hash the same and a scan with the fill restored finds it painted first, covering the page.
Edits and redactions after the fill are kept. When the original stream is still there with
the same bytes, the page points at it again. Otherwise the copy stays as it is, and
Remove background says which pages keep their own backdrop off: `EditNotice::BackdropsLeftOff`
(engine), a toast in the app, `warnings` from `doc_remove_marks`. `edit_notices` holds
`EditNotice` now, with the undrawn-text notice as one of its kinds. The two new UI strings
are in all 33 catalogues.

`sha2` (already in the lock file) becomes a dependency of `pdfcraft-edit`.

Tests, each seen failing with its piece of the fix reverted:
- `the_tag_holds_no_reference_and_a_full_save_keeps_no_second_copy_of_the_page` and
  `removed_text_leaves_the_file_when_a_background_replaced_the_pages_backdrop` (automation,
  redaction and Remove Hidden Information through a full save): fail with `/Original` back.
- `a_fill_that_would_cover_content_painted_before_it_stays_off`: fails without the re-scan.
- `a_copy_written_out_again_with_other_spacing_still_comes_back` and the automation test:
  fail when the raw bytes are hashed instead of the operators.
- `an_edit_after_the_fill_is_kept_and_the_backdrop_still_comes_back`: fails under the old
  rule (only an unchanged copy comes back).
- `remove_background_names_the_pages_whose_own_backdrop_stays_off` (engine),
  `remove_background_warns_about_pages_whose_own_backdrop_stays_off` (automation),
  `remove_background_says_which_pages_keep_their_own_backdrop_off` (UI): fail without the
  notice.
- `a_change_before_the_fill_leaves_it_off_and_names_the_page`,
  `a_tag_that_does_not_add_up_is_left_alone` (hostile and old-format tags, never a panic),
  `operators_hash_by_value_not_by_spelling`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 23:58:42 +02:00
alehel 5db4480b40 Merge remote-tracking branch 'origin/main' into fix/background-hidden-by-page-backdrop
# Conflicts:
#	parity/acrobat-features.toml
2026-10-22 18:04:34 +02:00