Skip to content

Fix notdef handling when subsetting Type 1 fonts#31928

Open
QuLogic wants to merge 1 commit into
matplotlib:mainfrom
QuLogic:fix-type1-subset
Open

Fix notdef handling when subsetting Type 1 fonts#31928
QuLogic wants to merge 1 commit into
matplotlib:mainfrom
QuLogic:fix-type1-subset

Conversation

@QuLogic

@QuLogic QuLogic commented Jun 20, 2026

Copy link
Copy Markdown
Member

PR summary

There's no guarantee that .notdef will appear as character code 0 in the encoding table [1], so always inserting it there may clobber an existing glyph. And in fact, with the strange encoding of Computer Modern, its symbol font does have an entry in 0 for the minus sign.

We only actually need .notdef in the todo list of charstrings to simulate, not in the encoding dictionary (which is only used again in _postscript_encoding, and that specifically ignores .notdef), so move it there.

Also, fix an inefficiency when simulating charstrings: once we simulate a glyph, it should be added to the done set immediately, otherwise it remains on the todo set, and gets simulated a second time (or possibly more since the set may pop in any order.)

[1] See the Adobe Type 1 Font Format specification in https://adobe-type-tools.github.io/font-tech-notes/pdfs/T1_SPEC.pdf which says that "A Type 1 font program must have a .notdef character defined in its CharStrings dictionary, even if it is not referenced by the encoding vector." but does not say it must be 0.

Fixes #31925, mostly. If you open the result file in a viewer (evince, ghostscript, firefox), then the minus sign is there, but it isn't there in the converted image used for comparisons. I suspect this may have to do with #30068.

AI Disclosure

None

PR checklist

There's no guarantee that `.notdef` will appear as character code 0 in
the encoding table [1], so always inserting it there may clobber an
existing glyph. And in fact, with the strange encoding of Computer
Modern, its symbol font _does_ have an entry in 0 for the minus sign.

We only actually need `.notdef` in the `todo` list of charstrings to
simulate, not in the `encoding` dictionary (which is only used again in
`_postscript_encoding`, and that specifically ignores `.notdef`), so
move it there.

Also, fix an inefficiency when simulating charstrings: once we simulate
a glyph, it should be added to the `done` set immediately, otherwise it
remains on the `todo` set, and gets simulated a second time (or possibly
more since the set may `pop` in any order.)

[1] See the Adobe Type 1 Font Format specification in
    https://adobe-type-tools.github.io/font-tech-notes/pdfs/T1_SPEC.pdf
    which says that "A Type 1 font program must have a `.notdef`
    character defined in its CharStrings dictionary, even if it is not
    referenced by the encoding vector." but does _not_ say it must be 0.
@QuLogic QuLogic added this to the v3.11.1 milestone Jun 20, 2026
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.

[Bug]: minus signs not rendered in PDF export with TeX

1 participant