Skip to content

feat(pptx): pixel-exact clipping via a rasterized composite fallback#412

Merged
DemchaAV merged 2 commits into
developfrom
feature/pptx-clip-raster
Jul 17, 2026
Merged

feat(pptx): pixel-exact clipping via a rasterized composite fallback#412
DemchaAV merged 2 commits into
developfrom
feature/pptx-clip-raster

Conversation

@DemchaAV

Copy link
Copy Markdown
Owner

Why

DrawingML has no graphics-state clipping, so clipped composites rendered unclipped — visibly different from the PDF: the vector parity demo's badge showed a whole circle where the PDF clips it to the rotated container outline.

What changed

  • PptxFixedLayoutBackend consumes the whole clip region (fragments between a clip-begin marker and its matching end, matched by owner path) and renders it through the PDF backend at up to 4 px/pt with a transparent background, crops the raster to the clip bounds, and places it as one picture. The clip is applied by the PDF engine itself — pixel-exact, including nested clips and transforms inside the region — and because the picture lands on the active drawing surface, an enclosing transform group still rotates and scales it.
  • The picture anchors on the crop's pixel bounds converted back to points (no visual shift from the floor/ceil snap); the raster is capped at 2048 px on the longest side. Fragment-level links, bookmarks, and anchors inside the region are still recorded; run-level hotspots inside a rasterized composite are not emitted.
  • On by default; Builder.clipRasterFallback(false) restores the previous unclipped vector rendering with its one-time warning (the clip-begin handler documents it now only dispatches on that path). Capability matrix flips the clip cell to supported-with-tradeoff; CHANGELOG entry added.

Verification

./mvnw -B -ntp clean verify (full 10-module reactor gate) → BUILD SUCCESS; render-pptx suite 39 → 41 tests.

PptxClipRasterFallbackTest pins both modes: exactly one transparent composite picture on the clip bounds whose centre pixel is opaque and whose corner outside the outline is fully transparent (the clip really cut the layer), no vector leak of the clipped content; and the disabled path rendering the unclipped vector with no composite picture. The vector parity demo's badge now matches the PDF page.

Lane: canonical (document.backend.fixed.pptx).

Stacked on #411 (fragment matrix) — merge #411 first.

@DemchaAV
DemchaAV changed the base branch from feature/pptx-vectors to develop July 17, 2026 14:12
DemchaAV added 2 commits July 17, 2026 15:12
DrawingML has no graphics-state clipping, so clipped composites rendered
unclipped — visibly different from the PDF (the parity demo's badge
showed a whole circle where the PDF clips it to the container outline).
The backend now consumes the whole clip region (the fragments between a
clip-begin marker and its matching end, found by owner path), renders it
through the PDF backend at up to 4 px/pt with a transparent background,
crops the raster to the clip bounds, and places it as one picture — the
clip is applied by the PDF engine itself, so the result is pixel-exact,
and because the picture is created on the active drawing surface an
enclosing transform group still rotates and scales it.

The picture anchors on the crop's pixel bounds converted back to points,
so the floor/ceil snap never shifts content. Fragment-level links,
bookmarks, and anchors inside the region are still recorded; the raster
is capped at 2048 px on the longest side. The fallback is on by default;
Builder.clipRasterFallback(false) restores the previous unclipped vector
rendering with its one-time warning, and the clip-begin handler now
documents that it only dispatches on that path.

PptxClipRasterFallbackTest pins both modes: one transparent composite
picture on the clip bounds with an opaque centre and a fully transparent
corner outside the outline (the clip really cut the layer), no vector
leak of the clipped content, and the disabled path rendering the
unclipped vector again. Full 10-module gate green; the vector parity
demo's badge now matches the PDF.
…tom handlers

The clip fallback rasterized the whole page at a scale keyed to the clip
box, so a small badge on a large canvas allocated a full-page raster per
region (hundreds of megabytes on poster-sized canvases). The region's
fragments now translate into a clip-sized canvas and only the clip box
renders — the raster is bounded by the capped clip size regardless of the
page, and the crop step disappears; the picture anchors directly on the
clip fragment box. A zero-size clip box skips drawing but still records
the region's navigation, and the interception respects Builder.addHandler:
a custom clip-begin handler keeps normal dispatch.

Tests sharpen to actually prove the cut: the sampled pixel lies inside the
layer circle but outside the container outline, so it is opaque in an
unclipped render and transparent only when the clip really cut the layer
(the old corner sample was transparent either way). New tests pin the two
headline behaviours: a clip inside a rotated container renders its
composite inside the rotated group, and a nested clip of a different owner
is consumed into one composite with both clips applied by the PDF
sub-render.
@DemchaAV
DemchaAV force-pushed the feature/pptx-clip-raster branch from fb8f96c to 64dc3c2 Compare July 17, 2026 14:12
@DemchaAV
DemchaAV merged commit c85cbef into develop Jul 17, 2026
12 checks passed
@DemchaAV
DemchaAV deleted the feature/pptx-clip-raster branch July 17, 2026 14:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant