Skip to content

fix(pdf): codepoint-aware symbol fallback; footnote cells keep fallback (#72) - #74

Merged
sonatique merged 2 commits into
mainfrom
fix/issue-72-pdf-symbol-fallback
Jun 20, 2026
Merged

fix(pdf): codepoint-aware symbol fallback; footnote cells keep fallback (#72)#74
sonatique merged 2 commits into
mainfrom
fix/issue-72-pdf-symbol-fallback

Conversation

@sonatique

Copy link
Copy Markdown
Owner

Fixes #72.

Problem

Two cases still emitted ? despite the #52 Unicode fallback (both render correctly in the Avalonia preview, so they're PDF-renderer-specific):

  • (A) Non-BMP characters render as ??. 🛇 (U+1F6C7) came out as two question marks — the UTF-16 surrogate pair was iterated as two code units, each half missing in every font.
  • (B) A footnote in a table cell disabled symbol fallback for that cell. An / that renders via the fallback font in a plain cell regressed to ? when the same cell also had a footnote:[…]. Cross-references did not trigger it; footnotes did.

Root cause & fix

(A) NeedsFallback/FontForChar/SplitFontRuns, the glyph encoder (EncodeTextAsGlyphIds/TrackCodePoints), and the WinAnsi escaper (EscapePdfString) all iterated char (UTF-16 code units). They now iterate Unicode codepoints via a shared EnumerateCodePoints helper, so a non-BMP character is one unit: it routes to the fallback font when covered, otherwise collapses to a single missing-glyph indicator — never ??.

(B) #69's segment-based cell path (RenderCellSegments) wrapped and wrote segments directly, skipping ExpandSegmentsForFallback — the step the body-text path (WriteWrappedSegments) runs. It now runs the same fallback expansion, so a footnote no longer disables fallback for sibling runs. (Confirmed body paragraphs were never affected.)

Before → after (literal base-font text from the repro)

  • Prohibited ?? signProhibited ? sign
  • footnote cell ? K [1] K [1] (the now uses the embedded fallback font)

Tests

Adds PdfSymbolFallbackTests: the single-missing-glyph behaviour for a non-BMP char (never ??), symbol fallback inside footnote-bearing cells (arrow + check mark), and a plain-paragraph regression guard for the #52 behaviour. Full Release suite green (0 failures, +4 tests); the 480 PDF/conformance/parity/font tests still pass.

Related: #52 (prior glyph/fallback fix), #69 (the table-cell segment path that regressed B).

Sylvain Fasel added 2 commits June 20, 2026 12:38
…ck (#72)

Two cases still emitted '?' despite the #52 Unicode fallback:

(A) Non-BMP characters rendered as '??'. NeedsFallback/FontForChar/SplitFontRuns,
the glyph encoder (EncodeTextAsGlyphIds/TrackCodePoints), and the WinAnsi escaper
(EscapePdfString) all iterated UTF-16 code units, so a surrogate pair was treated
as two characters — each half missing in every font, yielding two '?'. They now
iterate Unicode codepoints: a non-BMP codepoint routes to the fallback font when
covered, otherwise collapses to a single missing-glyph indicator — never '??'.

(B) A footnote in a table cell disabled symbol fallback for the rest of the cell.
#69's segment-based cell path (RenderCellSegments) wrapped and wrote segments
directly, skipping ExpandSegmentsForFallback, so '=>'/'✓' next to a footnote
regressed to base-font '?'. RenderCellSegments now runs the same fallback
expansion as the body-text path. Body paragraphs were unaffected (they already
go through WriteWrappedSegments).

Adds PdfSymbolFallbackTests covering the single-missing-glyph behaviour for a
non-BMP char, symbol fallback in footnote-bearing cells (arrow + check mark), and
a plain-paragraph regression guard.
@sonatique
sonatique merged commit 08316be into main Jun 20, 2026
4 checks passed
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.

PDF: symbol font-fallback breaks on non-BMP chars (=> ??) and in any footnote-bearing block (=> ?)

1 participant