Conversation
…rency regression fixtures (#119) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…n the compositor (#119) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…#119) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…nteraction, add tests and snapshots (#119) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…robe (#119) pdftransparencyrenderer.cpp already violated the format gate on dev; the gate checks whole touched files, so it is formatted here without other changes. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
| } | ||
|
|
||
| PDFOverprintProbe probe(session); | ||
| return &(cache[int(pageIndex)] = probe.probe(page, check.probeDpi, check.maxRasterPixels)); |
There was a problem hiding this comment.
The probe cache ignores per-check probe_dpi and max_raster_pixels. The cache is keyed by page index only, so the second of white-overprint and transparency-risk reuses the first one's raster. It then reports its own probe_dpi in the evidence, which is not the resolution actually used. Key the cache by (page, dpi, budget).
| /// True when the page, or a Form XObject it paints, declares overprint (/OP or /op true) in an | ||
| /// ExtGState. Only such pages are rasterized on the compositor, which keeps the cost off | ||
| /// the common case. | ||
| bool pageDeclaresOverprint(const PDFDocument* document, const PDFPage* page) |
There was a problem hiding this comment.
The overprint gate misses some resources. Only page and Form XObject ExtGStates are scanned. Overprint declared in pattern /Resources, soft-mask group (/SMask /G) resources or annotation appearance streams, or nested deeper than 8 levels, returns false. Those pages then get neither a compositor verdict nor a check-incomplete finding, so they pass clean.
| { | ||
| } | ||
|
|
||
| PDFOverprintProbeResult PDFOverprintProbe::probe(const PDFPage* page, int dpi, qint64 maxRasterPixels) |
There was a problem hiding this comment.
This duplicates PDFInkCoverageProbe::probe. About 50 lines are copied: box resolution, size and budget check, renderer settings, ink mapper and renderer construction. A shared "render page on the compositor" helper would keep the two probes from drifting apart. evaluateWhiteOverprintOnCompositor and evaluateTransparencyOverprintOnCompositor are also near-identical loops.
| } | ||
|
|
||
| PDFTransparencyRendererSettings rendererSettings; | ||
| rendererSettings.flags.setFlag(PDFTransparencyRendererSettings::SaveOriginalProcessImage, true); |
There was a problem hiding this comment.
Unused bitmap copy. SaveOriginalProcessImage makes the renderer keep a full-page float bitmap copy, but this probe only reads getOverprintObservation(). Drop the flag.
The probe cache was keyed by page only, so the second check reused the first check's raster. The overprint gate now also scans patterns, soft-mask groups and Type 3 fonts, and treats overly deep nesting as declaring overprint. Both compositor probes share raster setup, and the overprint probe no longer keeps an unused process bitmap. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Summary
Closes #119 (L01-14).
white-overprintandtransparency-risknow also consult the overprint-accurate compositor that Output Preview uses (PDFTransparencyRenderer, preflight-analysis policy), not only page-view overprint state.PDFOverprintObservation: overprinted pixels, paper-white overprinted pixels, overprinted pixels under a non-Normal blend mode, constant alpha below one or a knockout group). A newPDFOverprintProberenders a page and returns that observation./OPor/opin an ExtGState, including Form XObjects) are rasterized, once per run, atprobe_dpi.white-overprintadds a finding for paper-white pixels overprinted through paint the page-view scan does not inspect (images, shadings, transparency results).transparency-riskaddstransparency-overprint-interactionfor overprint composited with transparency. A page the compositor cannot judge (budget, render failure, non-exact overprint fidelity) reports an informationalcheck-incomplete.Proof
Fixtures
white-overprint-image.pdf(white CMYK image,op true, OPM 1, over cyan) andtransparency-overprint-knockout.pdf(black,op, OPM 1, alpha 0.5 in a knockout CMYK group) were committed first (generatorloop-preflight/tools/generate_white_overprint_compositor_fixture.py).pass: true, 0 warningswhite-overprintwarning, sourcecompositor, 7056 white overprinted pixelspass: true, 0 warningstransparency-overprint-interactionwarningBaseline
PdfToolwas built from the #118 head, which does not touch overprint code. Local (Windows, MSVC Release):UnitTestsPreflightEngine,UnitTestsPreflightCorpus,UnitTestsPreflightVerdict,UnitTestsPreflightChecks,UnitTestsEvidenceGraph,UnitTestsContentProcessorLimitsandUnitTestsOverprintRender(renderer goldens) all exit 0. Regenerating the corpus snapshots produced only the two new files, so the existing goldens are unchanged.generate-architecture-catalogs.py --check,check_source_integrity.py,check_preflight_truth_source.pyandcheck-change.py --dry-runpass. New tests cover both fixtures, a plain overprint page staying clean for transparency-risk, a page with no overprint not being rasterized, and the probe reporting a too-small budget as unrendered.An early version also counted antialiased edge coverage as transparency and changed five existing overprint goldens; I removed that criterion rather than re-baselining them.
Not run locally
Full
check-changebuild/ctest/clang-tidy (noclang-tidy-18), Linux lanes, and the remaining mapped test targets (includingUnitTestsPageSurface); left to CI.Remaining risk
probe_dpiand not annotation appearances; only pages that declare overprint are rasterized.Handoff
Changed:
pdftransparencyrenderer.*(observation counters),pdfinkcoverageprobe.*(PDFOverprintProbe),preflightengine.*(declaration scan, probe cache, two evaluators), tests, fixtures and generator, two snapshots, overlay (both rows landed, closed_by their check ids), regenerated catalogs, README, change record and evidence. Anti-slop review: no new profile parameters, the compositor is observed rather than modified, and uncertainty is reported ascheck-incompleteinstead of guessed.🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.