Request to support PostScript-flavoured (CFF) OpenType fonts in PDF backend · Issue #2869 · matplotlib/matplotlib · GitHub
Skip to content

Request to support PostScript-flavoured (CFF) OpenType fonts in PDF backend #2869

Open

Description

@mojca

I would like to request support for OpenType fonts. I have the main text written with Lucida and I'm unable to get the font on the graphs match the ones in the text.

I'm using the latest matplotlib with Python 3.3 on Mac OS X 10.7. When I try to use any give OpenType font

matplotlib.rcParams['font.family'] = 'Any Name Of OpenType Font'

this is what I get:

Traceback (most recent call last):
  File "test.py", line 26, in <module>
    plt.savefig('test.pdf')
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/site-packages/matplotlib/pyplot.py", line 571, in savefig
    res = fig.savefig(*args, **kwargs)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/site-packages/matplotlib/figure.py", line 1448, in savefig
    self.canvas.print_figure(*args, **kwargs)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/site-packages/matplotlib/backend_bases.py", line 2192, in print_figure
    **kwargs)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/site-packages/matplotlib/backends/backend_pdf.py", line 2476, in print_pdf
    file.close()
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/site-packages/matplotlib/backends/backend_pdf.py", line 528, in close
    self.writeFonts()
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/site-packages/matplotlib/backends/backend_pdf.py", line 631, in writeFonts
    fonts[Fx] = self.embedTTF(realpath, chars[1])
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/site-packages/matplotlib/backends/backend_pdf.py", line 1106, in embedTTF
    return embedTTFType3(font, characters, descriptor)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/site-packages/matplotlib/backends/backend_pdf.py", line 892, in embedTTFType3
    filename.encode(sys.getfilesystemencoding()), glyph_ids)
RuntimeError: TrueType font is missing table

The weird thing is that my colleagues get a different warning (complaining that font substitution isn't supported and then some garbled output).

The problem is that apparently backend_pdf.py is only taking
into account:

  • *.afm fonts
  • something with dvi info (which came from TeX)
  • everything else is treated as TTF, so it goes though ttconv which apparently isn't able to handle PostScript-flavoured fonts

The interactive display and PNG work just fine, but I would like to have vector graphics.

I then tried to fetch a TrueType version of Lucida from Java, but that one behaves weird enough that I'm unable to use it (I'll open a new issue for that). I also experienced something very very odd – fonts from those fonts are rendered on our high end laser printer as if they were high resolution bitmap images, somewhat fuzzy. Fonts from gnuplot graphics and the rest of text is crisp clear, while text from pyplot graphs is somewhat smoothed at the edges, it looks like rasterized or weirdly hinted font.

An alternative would be to render the text labels through TeX, but I don't know how to set it up for (OpenType) Lucida fonts. (I know how to set it up outside of matplotlib.)

A slightly related issue is #1366. It would be great if pyplot supported OpenType Math fonts indeed, like Latin Modern Math, XITS Math, TeX Gyre Math (basically Helvetica, Times, Palatino, Bookman), Lucida Bright Math, Cambria, ...

Activity

  1. mdboom commented on Mar 11, 2014

    @mdboom
    Member

    There was some abandoned work to get this done by replacing FT2Font and ttconv with a more modern freetype wrapper that gives us what we need to do the font subsetting for any font that freetype supports. The wrappers are mostly done: https://github.com/matplotlib/freetypy, but things stalled getting this then integrated with matplotlib, as I lost time to work on it. I'd love to see someone take that on, but it's a fair bit of work.

  2. added this to the milestone on Mar 11, 2014
  3. mojca commented on Mar 11, 2014

    @mojca
    Author

    Are you able to provide a short list of things that need to be done? (And maybe the desired skillset?)
    What is the relation between this change and support for, say, OpenType Math layout?
    Just brainstorming: would it help if one of TeX user groups would provide a tiny bit of funding in the name of "better support for graphs, compatible with TeX documents"?

  4. mdboom commented on Mar 11, 2014

    @mdboom
    Member

    You can read MEP14 : https://github.com/matplotlib/matplotlib/wiki/Mep14. It actually has a much larger scope than just this -- the relevant sections to this bug are "Font subsetting" and "Freetype wrappers".

    Essentially, all of the calls to FT2Font (the current matplotlib freetype wrapper) and ttconv (the TTF-only font subsetting code) would need to be replaced with calls to the new freetypy wrapper (which is mostly complete -- just missing a little final polish). The ttconv code will need to directly convert the outlines obtained from freetypy into the native outline format of PDF, PS, SVG etc. directly in Python (rather than using C as ttconv does now). At least the Agg, PDF, PS and SVG backends as well as the path effects stuff will be affected. The skill set required is mostly Python at this point (the C parts are mostly done), but it does require understanding the font outline API of freetype and the font outline formats of PS, PDF and SVG.

    OpenType Math layout is somewhat orthogonal to this. Here, we're talking only about supporting the OpenType file format, as opposed to the TrueType file format, without using any of the OpenType specific features and information. OpenType Math layout allows the font to specify certain things about the math layout -- such as how deep subscripts should be etc. -- that the layout engine would use to adapt itself to a particular font. My understanding is that STIX does not have this information, but there is a fork, XITS, that aims to add it.

    Funding always helps, but we'd also need someone with the time... ;) I'm not sure that's me at the moment.

  5. added and removed on Sep 20, 2014
  6. petehuang commented on Jan 7, 2017

    @petehuang
    Contributor

    Just tossing in an update: doesn't seem like there's been any movement, please comment if otherwise

  7. modified the milestones: , on Oct 3, 2017
  8. anntzer commented on Nov 7, 2018

    @anntzer
    Contributor

    If you're still interested: the https://github.com/anntzer/mplcairo backend should support all reasonably common font formats.

  9. github-actions commented on Mar 4, 2023

    @github-actions

    This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!

  10. mojca commented on Mar 5, 2023

    @mojca
    Author

    Still interested

  11. oscargus commented on Mar 5, 2023

    @oscargus
    Member

    There seems to be alternative bindings now: https://pypi.org/project/freetype-py/

  12. added
    keepItems to be ignored by the “Stale” Github Action
    and removed
    status: inactiveMarked by the “Stale” Github Action
    on Mar 5, 2023
  13. QuLogic commented on Jul 1, 2025

    @QuLogic
    Member

    ttconv was replaced in #20866, but without a specific (non-proprietary) font to test, I cannot confirm whether this is working or not, but I suspect it was fixed.

  14. lstngr commented on Dec 3, 2025

    @lstngr

    I'm also interested in this! The situation seems to have improved since the ticket was opened (a PDF is generated), but the resulting file appears to be malformed?

    In particular, many LaTeX OTF fonts (distributed by, e.g., TeXLive) seem to originate from a Postscript format and trigger this error:

    import matplotlib as mpl
    import matplotlib.pyplot as plt
    
    # A copy of TeX Gyre Heros can also be found here: https://www.gust.org.pl/projects/e-foundry/tex-gyre/heros
    mpl.rcdefaults()
    mpl.rcParams["pdf.fonttype"] = 42
    mpl.rcParams["font.sans-serif"] = ["TeX Gyre Heros"] + mpl.rcParamsDefault["font.sans-serif"]
    
    plt.subplots()
    plt.savefig("/tmp/text.pdf")

    Executing pdffonts /tmp/text.pdf yields:

    Syntax Warning: Mismatch between font type and embedded font file
    name                                 type              encoding         emb sub uni object ID
    ------------------------------------ ----------------- ---------------- --- --- --- ---------
    CCVYUO+TeXGyreHeros-Regular          CID Type 0C (OT)  Identity-H       yes yes yes     15  0
    

    If the default font, DejaVu Sans, is used, the output is:

    name                                 type              encoding         emb sub uni object ID
    ------------------------------------ ----------------- ---------------- --- --- --- ---------
    BMQQDV+DejaVuSans                    CID TrueType      Identity-H       yes yes yes     15  0
    

    In the current Matplotlib version, this seems to be due to the following backend location, which hardcodes the font type when Opentype output is requested. In this backend, CIDFontType2 supposedly indicates the font is in Truetype format.
    The hardcoded behavior can be checked by decompressing the output PDF:

    # pdftk /tmp/text.pdf output /tmp/text-uncompr.pdf uncompress
    # grep -aC3 CID /tmp/text-uncompr.pdf
    15 0 obj
    
    <<
    /Subtype /CIDFontType2
    /CIDSystemInfo 
    <<
    /Supplement 0
    /Registry (Adobe)
    --
    /BaseFont /CCVYUO+TeXGyreHeros-Regular
    /FontDescriptor 13 0 R
    /W 16 0 R
    /CIDToGIDMap 17 0 R
    >>
    endobj
    
    --
    /Length 460
    >>
    stream
    /CIDInit /ProcSet findresource begin
    12 dict begin
    begincmap
    /CIDSystemInfo
    << /Registry (Adobe)
       /Ordering (UCS)
       /Supplement 0
    

    I'm far from knowledgeable on this topic, so I hope my conclusions are not erroneous and that this helps!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions