Skip to content

pdf/ps: Stop retaining glyph indices in font subsets#31975

Merged
ksunden merged 2 commits into
matplotlib:mainfrom
QuLogic:drop-subset-glyphs
Jul 10, 2026
Merged

pdf/ps: Stop retaining glyph indices in font subsets#31975
ksunden merged 2 commits into
matplotlib:mainfrom
QuLogic:drop-subset-glyphs

Conversation

@QuLogic

@QuLogic QuLogic commented Jun 30, 2026

Copy link
Copy Markdown
Member

PR summary

When passing retain_gids=True to the subsetter, it keeps all glyphs until the last one used, in order to preserve the order. For unused glyphs, the data is removed, but metadata about them remains.

For example, in DejaVu Sans, the 'fl' ligature is glyph index 5040; this means you get >5000 unused (but empty) glyphs even when that is the only character used from the font subset. If a file uses multiple subsets, each one could contribute an extra copy of the common lower end of the glyph table (e.g., the Latin alphabet, punctuation, etc.)

In PostScript, glyphs are referenced by their name and so the glyph index is unimportant. In PDF, the same is true when embedding Type 3 fonts. When embedding Type 42 fonts in PDF, all text is output as character codes, which have their own mapping to glyph indices in each font. Since we already have to output this information, we just need to adjust it slightly to have the glyph index in the subsetted font, and then we can drop the retain_gids option.

Depending on which is the last glyph in a subset, how many glyphs are in a font, and how many subsets are necessary, this can have a significant impact on the resulting file size. As an example from our test baseline images:

  • test_backend_pdf/multi_font_type42.pdf: 154239 -> 75304 bytes (>50% saved)
  • test_backend_pdf/ttc_type42.pdf: 185702 -> 9803 bytes (almost 95% saved)
  • test_backend_ps/multi_font_type42.eps: 761648 -> 198585 bytes (almost 75% saved)
  • test_backend_ps/type42_without_prep.eps: 1538967 -> 15978 bytes (almost 99% saved)

Fixes #31955

AI Disclosure

None

PR checklist

@QuLogic

QuLogic commented Jun 30, 2026

Copy link
Copy Markdown
Member Author

Note, I have updated the test image here that had the most significant file size changes so we aren't carrying them around needlessly. Note however, it was not necessary to do so as this is just removing unused cruft and tests passed without the new images.

@github-actions github-actions Bot added the CI: Run cibuildwheel Run wheel building tests on a PR label Jul 1, 2026
QuLogic added 2 commits June 30, 2026 20:47
When passing `retain_gids=True` to the subsetter, it keeps all glyphs
until the last one used, in order to preserve the order. For unused
glyphs, the data is removed, but metadata about them remains.

For example, in DejaVu Sans, the 'fl' ligature is glyph index 5040; this
means you get >5000 unused (but empty) glyphs even when that is the only
character used from the font subset. If a file uses multiple subsets,
each one could contribute an extra copy of the common lower end of the
glyph table (e.g., the Latin alphabet, punctuation, etc.)

In PostScript, glyphs are referenced by their name and so the glyph
index is unimportant. In PDF, the same is true when embedding Type 3
fonts. When embedding Type 42 fonts in PDF, all text is output as
character codes, which have their own mapping to glyph indices in each
font. Since we already have to output this information, we just need to
adjust it slightly to have the glyph index in the subsetted font, and
then we can drop the `retain_gids` option.

Depending on which is the last glyph in a subset, how many glyphs are in
a font, and how many subsets are necessary, this can have a significant
impact on the resulting file size. As an example from our test baseline
images:

- `test_backend_pdf/multi_font_type42.pdf`: 154239 -> 75304 bytes (>50%
  saved)
- `test_backend_pdf/ttc_type42.pdf`: 185702 -> 9803 bytes (almost 95%
  saved)
- `test_backend_ps/multi_font_type42.eps`: 761648 -> 198585 bytes
  (almost 75% saved)
- `test_backend_ps/type42_without_prep.eps`: 1538967 -> 15978 bytes
  (almost 99% saved)
This is the first version to save the glyph mapping from original to
subset font.
@QuLogic QuLogic force-pushed the drop-subset-glyphs branch from 2ff2593 to f6d83e4 Compare July 1, 2026 00:47

@tacaswell tacaswell left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the age of fonttools 4.28.2 I think it is OK to bump the version in 3.11.1.

@ksunden ksunden merged commit 1b5f691 into matplotlib:main Jul 10, 2026
46 checks passed
@QuLogic QuLogic deleted the drop-subset-glyphs branch July 10, 2026 18:26
QuLogic added a commit that referenced this pull request Jul 15, 2026
…975-on-v3.11.x

Backport PR #31975 on branch v3.11.x (pdf/ps: Stop retaining glyph indices in font subsets)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: PDF Type 42 output regression in 3.11: excessive font embedding and fl rendered as a ligature

3 participants