Skip to content

Version 2.0.0_1 breaks OpenType font character spacing on PDF save #8050

Closed

Description

@andermannlab

Bug report

Bug summary

I know that Matplotlib does not officially support OpenType fonts, but I have successfully been using them for axis labels in version 1.5.3 and earlier. I just updated Matplotlib via Macports and the character spacing and alignment broke, especially with larger font sizes. For example, X axis titles that are centered begin at the same position, but have extra wide spacing. This is found with all OpenType fonts that I have tried.

Code for reproduction

  • This requires the free font Canter (not ideal for graphing, but it is available for testing), but can be reproduced with other fonts.
  • I have only included my setting of the fonts and saving the PDF, as this can be reproduced with any plot I've made.
import matplotlib as mpl
import matplotlib.pyplot as plt
f = {'family':'Canter;, 'weight':'light', 'size':20}
mpl.rc('font', **f)

plt.savefig('test.pdf', transparent=True)

Actual outcome

170208-correlation-version 2.pdf

Expected outcome

170208-correlation-version 1.5.pdf

  • This worked in v 1.5.3 and does not work in 2.0.0

Matplotlib version

  • Python 2.7, Matplotlib versions 1.5.3 and 2.0.0, installed via macports

Activity

  1. QuLogic commented on Feb 8, 2017

    @QuLogic
    Member

    Might be related to #7937?

  2. afvincent commented on Feb 9, 2017

    @afvincent
    Contributor

    FWIW, I tried to reproduce this bug (on CentOS 7) with ComicNeue_Light.otf (in the current directory) and the following script

    import matplotlib as mpl
    import matplotlib.pyplot as plt
    from matplotlib.font_manager import FontProperties
    
    plt.style.use('classic')  # to be ~ consistent between mpl versions
    fig, ax = plt.subplots(num="mwe")
    ax.plot([-5, 0, 5], [0.9, -0.85, 0.7])
    
    # Add some labels with OTF font
    fprops = FontProperties(fname='./ComicNeue_Light.otf', weight='light', size=32)
    ax.set_xlabel("X-axis testing",fontproperties=fprops)
    ax.set_ylabel("Y-axis testing",fontproperties=fprops)
    ax.set_title("mpl v" + mpl.__version__, fontproperties=fprops, fontsize=12)
    # Adjust tick labels to the OTF font
    for label in ax.get_xticklabels() + ax.get_yticklabels():
        label.set_fontproperties(fprops)
    
    plt.tight_layout()
    fig.savefig(fig.get_label() + "_" + mpl.__version__ + ".pdf")

    What I get is:

    Except the missing “-” glyph, nothing does really looks wrong with 1.5.1, and I get the same text rendering as with 2.0.0rc1. With a recent mpl version from master, the spacing between the glyphs is a bit smaller than with the former mpl versions

  3. afvincent commented on Feb 9, 2017

    @afvincent
    Contributor

    Oh I thought it would be difficult to get the Canter font, but actually it was not (freely available here). So the results are similar to the ones with ComicNeue, i.e. I cannot reproduce the bug :/. What I get is:

  4. tacaswell commented on Feb 9, 2017

    @tacaswell
    Member

    Might need to delete the mpl font cache?

  5. andermannlab commented on Feb 9, 2017

    @andermannlab
    Author

    I have tried to delete the font cache and that was not successful. I have made a minimal example that continues to work in version 1.5.3 and fail in version 2.0.0. I was not using FontProperties, though.

    import matplotlib as mpl
    import matplotlib.pyplot as plt
    
    f = {'family':'Canter', 'weight':'light', 'size':20}
    mpl.rc('font', **f)
    
    x = [-4,-3,-2,-1.0001,0,1,2,3,4]
    y = [0.019,-0.097,-0.343,-0.521,-0.327,-0.362,-0.129,-0.168,-0.078]
    
    fig = plt.figure(figsize=(7.5, 6))
    ax = plt.subplot(111)
    ax.plot(x, y, linewidth=0.5, alpha=0.2, color='#666666')
    
    ax.set_xlabel('LONG XLABEL TESTING')
    ax.set_ylabel('LONGER YLABEL TESTING')
    
    plt.savefig('test.pdf', transparent=True)
  6. afvincent commented on Feb 9, 2017

    @afvincent
    Contributor

    NB: I am using FontProperties because Canter fonts are not installed on my OS (and they do not seem to be available in CentOS 7 repositories).

    I tried @andermannlab 's example with FontProperties (else I fallback to DejaVu or Bitstream fonts…) and the results are the same as my previous trials. @andermannlab Could you test it using FontProperties please? Just to see if you still have the issue on your side.

  7. andermannlab commented on Feb 9, 2017

    @andermannlab
    Author

    I have just tried the FontProperties version and it works (with multiple OpenType fonts, including Canter). Thank you.

    Is the long-term solution to transition legacy code to FontProperties?

  8. afvincent commented on Feb 9, 2017

    @afvincent
    Contributor

    Honestly I know almost nothing about how fonts are handled in matplotlib, so currently I would simply consider this as a workaround to your problem. Maybe one of the core devs will know more.

  9. added this to the milestone on Feb 10, 2017
  10. grahamrow commented on Feb 10, 2017

    @grahamrow

    It is related to #7937, I've been solving this with a monkeypatch from the patch mentioned in that issue. I'm using otf fonts, and confirm that it works:

    import matplotlib.font_manager as fm
    from matplotlib.ft2font import FT2Font
    def get_font(*args, **kwargs):
        return FT2Font(*args, **kwargs)
    fm.get_font = get_font
    

    BUT, the whole darned font gets added to the pdf since subsetting is broken. I run the pdf through ghostscript afterwards, which properly subsets. I use an ipython shell command to do this for me:

    def gs(filename):
        command = "gs -o {} -q -dNOPAUSE -sDEVICE=pdfwrite -dBATCH -dSAFER -dPDFSETTINGS=/prepress " \
                  "-dAutoRotatePages=/None -dDownsampleColorImages=false -dDownsampleGrayImages=false " \
                  "-dDownsampleMonoImages=false -dAutoFilterColorImages=false -dColorImageFilter=/FlateEncode " \
                  "-dAutoFilterGrayImages=false -dGrayImageFilter=/FlateEncode {}"
        return command.format(filename[:-4]+'-gs.pdf', filename)
    # Run with: !{gs("test")}
    
  11. QuLogic commented on Feb 10, 2017

    @QuLogic
    Member

    Can you try with the fix in #7961 and not the workaround from #7937?

  12. jkseppan commented on Feb 11, 2017

    @jkseppan
    Member

    Did subsetting ever work for otf fonts?

  13. tacaswell commented on Feb 11, 2017

    @tacaswell
    Member

    That is a @mdboom question, but I think the answer is no.

  14. QuLogic commented on Feb 26, 2017

    @QuLogic
    Member

    Ping @andermannlab and @grahamrow; please try with #7961 or I'm going to close this eventually.

  15. grahamrow commented on Feb 27, 2017

    @grahamrow

    Thanks @QuLogic and @jkseppan, this does appear to have solved the issue. Master branch works properly after the #7961 merge, no need for the workaround anymore.

    I have a feeling it's a pretty deep rabbit hole, but I might start looking into the subsetting issue.

  16. jkseppan commented on Feb 27, 2017

    @jkseppan
    Member
  17. QuLogic commented on Apr 15, 2017

    @QuLogic
    Member

    I'm going to close this since at least one reporter has confirmed it's working.

  18. modified the milestones: , on Apr 15, 2017
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

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions