Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
andermannlab opened this issue Feb 8, 2017 · 16 comments
Closed
Milestone

Comments

@andermannlab
Copy link

andermannlab commented Feb 8, 2017

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
@QuLogic
Copy link
Member

QuLogic commented Feb 8, 2017

Might be related to #7937?

@afvincent
Copy link
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

@afvincent
Copy link
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:

@tacaswell
Copy link
Member

Might need to delete the mpl font cache?

@andermannlab
Copy link
Author

andermannlab commented Feb 9, 2017

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)

@afvincent
Copy link
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.

@andermannlab
Copy link
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?

@afvincent
Copy link
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.

@tacaswell tacaswell added this to the 2.1 (next point release) milestone Feb 10, 2017
@grahamrow
Copy link

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")}

@QuLogic
Copy link
Member

QuLogic commented Feb 10, 2017

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

@jkseppan
Copy link
Member

Did subsetting ever work for otf fonts?

@tacaswell
Copy link
Member

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

@QuLogic
Copy link
Member

QuLogic commented Feb 26, 2017

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

@grahamrow
Copy link

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.

@jkseppan
Copy link
Member

jkseppan commented Feb 27, 2017 via email

@QuLogic
Copy link
Member

QuLogic commented Apr 15, 2017

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

@QuLogic QuLogic closed this as completed Apr 15, 2017
@QuLogic QuLogic modified the milestones: 2.0.1 (next bug fix release), 2.1 (next point release) Apr 15, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants