Skip to content

fix(afm): treat UTF-16 surrogate pairs as single code points - #1854

Merged
blikblum merged 1 commit into
foliojs:masterfrom
juancarlosmorato-aircury:fix/afm-surrogate-pairs
Nov 2, 2026
Merged

blikblum merged 1 commit into
foliojs:masterfrom
juancarlosmorato-aircury:fix/afm-surrogate-pairs

Conversation

@juancarlosmorato-aircury

@juancarlosmorato-aircury juancarlosmorato-aircury commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

What kind of change does this PR introduce?

Bug fix for UTF-16 surrogate pairs in standard (AFM) fonts.

Minimal reproduction (latest @react-pdf/renderer@4.9.0)

Rendering 𝑥 (U+1D465) or 🅪🅫 (U+1F16A/U+1F16B) with Helvetica produces garbage such as 5e / <j<k> instead of a single .notdef (or the real glyph when a supporting font is used).

What is still needed after diegomura/react-pdf#3423 and #3509?

Piece from diegomura/react-pdf#3133 Status after #3423 + #3509
textkit font substitution (codePointAt) Fixed in #3423 (in 4.9.0)
AFM encodeText / glyphsForString Still broken — lived in react-pdf’s pdfkit fork; #3509 switched react-pdf to official pdfkit@0.20.1, which still uses charCodeAt

Upstream repo for the remaining fix: foliojs/pdfkit (this PR).

encodeText / glyphsForString now iterate with codePointAt and advance by 1 or 2 so each supplementary-plane character is one unit.

Related: diegomura/react-pdf#3127, diegomura/react-pdf#3133 (AFM portion superseded here).

Checklist:

  • Unit Tests
  • Documentation N/A
  • Update CHANGELOG.md
  • Ready to be merged

AFMFont.encodeText/glyphsForString walked strings with charCodeAt, so
supplementary-plane characters were encoded as two WinAnsi halves and
rendered as garbage (e.g. U+1D465 → "5e", U+1F16A/B → "<j<k").

Iterate with codePointAt instead. Fixes the remaining half of
diegomura/react-pdf#3127 after textkit's #3423, now that react-pdf
depends on upstream pdfkit (#3509). Supersedes the AFM portion of
diegomura/react-pdf#3133.
@blikblum
blikblum merged commit c21dfa5 into foliojs:master Nov 2, 2026
3 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.

2 participants