feat(pptx): warn explicitly whenever a font is substituted in the deck#410
Merged
Conversation
A font that cannot travel into the .pptx identically now says so, once per family per render pass, on the render logger: standard-14 families warn with their metric-compatible replacement (Helvetica renders as Arial — identical widths, slightly different letterforms); families registered without binary sources and unregistered font names warn that the deck carries a name-only reference that viewers without the font will substitute; license-restricted embeds already warned. An embedded family stays silent — registering binary sources (registerFontFamily) remains the way to guarantee identical glyphs in both formats on any machine. PptxFontMapping.standardReplacementFor exposes the replacement decision; PptxFontSubstitutionWarningTest pins all three outcomes and the once-per-family semantics through a logback appender.
Renders the same specimen line (regular/bold/italic plus a size ramp) through four embedded families — Lato, Poppins, JetBrains Mono, Spectral — into the PDF/PPTX pair under target/visual-tests/pptx-parity/font-identity/. Both outputs embed the same TTF programs, so a real viewer shows identical glyphs; the specimen exists to check that claim by eye, page against slide.
…matrix note Substitution warnings now dedupe on the resolved viewer family, so facet-suffixed names (Roboto-Regular, Roboto-Bold) warn once per family per render while the message still names the source font the document asked for. A family whose embed fails also emits the shared render.pptx.font.substitution key — one log filter now catches every substitution — alongside the cause-carrying embed-skip warning. familyFor delegates to standardReplacementFor, collapsing the third prefix switch on the same standard-14 names. The capability matrix states the explicit-substitution contract (the sentence previously missed the file). The specimen demo now asserts the deck actually embeds all four families; the warning test covers the facet dedupe and stops its appender.
DemchaAV
force-pushed
the
feature/pptx-font-substitution-warnings
branch
from
July 17, 2026 11:27
4eff84a to
848f0f9
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A font that cannot travel into the .pptx identically was substituted silently in two of three cases: standard-14 families render as their metric-compatible replacements (Helvetica → Arial — identical widths, slightly different letterforms), and families without binary sources reach the deck as name-only references that viewers substitute at open time. Only license-restricted embeds warned. Silent substitution makes the letterform difference look like a rendering bug.
What changed
PptxRenderEnvironment.fontFamilywarns once per family per render pass on the render logger (render.pptx.font.substitution): standard-14 families name their replacement and point atregisterFontFamilyfor identical glyphs; unregistered names and families registered without binary sources are flagged as name-only references. An embedded family stays silent.PptxFontMapping.standardReplacementForexposes the replacement decision (used by the warning and available to callers).Verification
./mvnw -B -ntp test -pl :graph-compose-render-pptx -am→ BUILD SUCCESS, suite 32 → 33 tests.PptxFontSubstitutionWarningTestpins all three outcomes and the once-per-family semantics through a logback appender: two warnings for Helvetica + an unregistered name, none for the embedded Lato family, no duplicates on repeated lookups.Lane: canonical (document.backend.fixed.pptx).
Stacked on #409 (table rows) — merge #409 first.