Skip to content

pptx: replace the clip raster fallback with true vector clipping #413

Description

@DemchaAV

Current state (the workaround)

DrawingML has no graphics-state clipping, so the fixed-layout PPTX backend cannot express ShapeClipBegin/EndPayload regions the way the PDF backend does (q → path → clip → Q).

Since #412 the backend uses a raster fallback (on by default): the whole clip region — the fragments between a clip-begin marker and its matching end — is translated onto a clip-sized canvas, rendered through PdfFixedLayoutBackend.renderToImages at up to 4 px/pt (capped at 2048 px) with a transparent background, and placed as one picture ("GraphCompose Clipped Composite") on the clip bounds. PptxFixedLayoutBackend.Builder.clipRasterFallback(false) restores the previous behaviour: children render unclipped with a one-time warning.

This is visually exact (the clip is applied by the PDF engine itself, nested clips and enclosing transform groups included) but it is still a workaround:

  • the clipped composite is not editable as shapes in PowerPoint — it degrades to a bitmap island inside an otherwise vector slide;
  • text inside a clipped container loses selectability and crispness at high zoom;
  • run-level link hotspots inside the rasterized region are not emitted (fragment-level links/bookmarks/anchors are still recorded);
  • every clip region costs a PDF sub-render (fonts, save, reload, raster) at .pptx export time.

Entry point: PptxFixedLayoutBackend.renderClippedComposite (render-pptx, document.backend.fixed.pptx). Status is documented in docs/architecture/backend-capability-matrix.md (clip row).

Candidate proper solutions

  1. Analytical vector intersection (preferred for vector children). Clip each child's geometry against the outline path on the Java side — java.awt.geom.Area boolean ops over the freeform paths — and emit the intersected paths as normal freeform shapes. Exact and fully editable for shape/polygon/path/ellipse children. Does not cover text or images.
  2. Per-child picture crops. A picture child whose clip intersection is an axis-aligned rectangle maps to the native srcRect crop (the COVER-fit machinery already does this). Covers the common "image in a rounded card" case without rasterizing.
  3. Hybrid dispatch (the likely end state). Per child inside the clip region: vector children → Area intersection (1); picture children with rect-reducible clips → srcRect (2); text and anything unrepresentable → rasterize only those children, not the whole region. The existing raster fallback remains the last-resort branch and the clipRasterFallback(false) escape hatch stays.
  4. Text-to-outlines for clipped text. Convert clipped text runs to path outlines (glyph vectors from the embedded font) and then intersect as in (1). Keeps vectors at the price of text editability — arguably no better than the raster for text, but resolution-independent.

Acceptance criteria

  • A clipped composite made of vector children exports as clipped vector shapes (no picture), byte-comparable geometry with the PDF render at ≤0.5pt.
  • Picture children with rectangular clip intersections use srcRect, not rasterization.
  • The raster branch remains only for children that genuinely cannot be represented, and the capability matrix row is updated to reflect the narrowed scope.
  • Existing tests in PptxClipRasterFallbackTest keep passing where they pin behaviour that stays (transform interaction, navigation recording, the disable flag).

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions