Skip to content

feat(pptx): raster-slide mode — pixel-exact full-slide pictures#408

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

feat(pptx): raster-slide mode — pixel-exact full-slide pictures#408
DemchaAV merged 2 commits into
developfrom
feature/pptx-raster-slides

Conversation

@DemchaAV

Copy link
Copy Markdown
Owner

Why

The vector PPTX backend guarantees identical geometry, but glyph rasterization ultimately belongs to the viewer's font engine — a deck opened on a machine without the document fonts (or with embedding-restricted fonts) renders substitute glyphs. Some decks must look pixel-identical to the PDF/PNG output everywhere, and are happy to pay with editability.

What changed

  • PptxFixedLayoutBackend.Builder.rasterSlides(int dpi) (new, @since 2.1.0): raster-slide mode. Every page renders through PdfFixedLayoutBackend.renderToImages at the given DPI and lands as one full-slide PNG picture anchored to the exact slide bounds — a pixel-exact copy of the PDF/PNG output in .pptx form.
  • The editable vector mode stays the default and the ServiceLoader provider path is untouched; raster mode is opt-in per backend instance. Trade-offs are documented on the builder: slide content is a picture (no text selection/editing), file size grows with resolution.

Verification

./mvnw -B -ntp test -pl :graph-compose-render-pptx -amBUILD SUCCESS, render-pptx suite 26 → 28 tests.

PptxRasterSlidesTest pins the contract: one picture per page across a page break, anchored at (0, 0, canvasWidth, canvasHeight); picture bytes equal the independently encoded session.toImages PNG at the same DPI (byte-for-byte); and the default mode still emits vector shapes (no pictures).

Notes

Lane: canonical (document.backend.fixed.pptx) — additive backend option; vector path untouched.

@DemchaAV
DemchaAV changed the base branch from feature/pptx-text to develop July 17, 2026 09:56
@DemchaAV
DemchaAV force-pushed the feature/pptx-raster-slides branch from e4ad54a to 705df99 Compare July 17, 2026 09:57
DemchaAV added 2 commits July 17, 2026 11:01
PptxFixedLayoutBackend.Builder.rasterSlides(int dpi) renders every page
through the PDF backend at the given DPI and places it as one full-slide
picture, so the deck is a pixel-exact copy of the PDF/PNG output — for
decks that must look identical on any machine regardless of fonts. The
trade-off is a picture per slide: text is not selectable or editable and
files grow with resolution, so the editable vector mode stays the default
and the provider path is untouched.

PptxRasterSlidesTest pins the contract: one picture per page anchored to
the full slide, picture bytes equal to the independently encoded
session.toImages output at the same DPI, and the default mode still
emitting vector shapes.
The viewer-ascent formula lived twice — in the render environment and,
line for line, in the geometry-test mirror — so the geometry gate only
proved the two copies agreed. PptxViewerMetrics.ascentPoints is now the
single resolver both sides call, and the anti-tautology check is a
hand-computed constant pinned in PptxFontMappingTest (Arial hhea ascent:
22pt x 1854/2048 = 19.916015625pt exactly).

Raster-slide mode caps the resolution at 600 DPI — every page is held in
memory during the render, so an unbounded value died later as an opaque
OutOfMemoryError inside PDFBox — and its javadoc now states the memory
profile and that hyperlinks, bookmarks, and custom fragment handlers do
not apply to raster slides. Fully-qualified names in the raster path
replaced with imports.
@DemchaAV
DemchaAV force-pushed the feature/pptx-raster-slides branch from 705df99 to 46ce727 Compare July 17, 2026 10:01
@DemchaAV
DemchaAV merged commit ec0e3ed into develop Jul 17, 2026
12 checks passed
@DemchaAV
DemchaAV deleted the feature/pptx-raster-slides branch July 17, 2026 10:05
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