-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Large TrueType font does not render correctly when saving in .pdf #7937
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
Comments
Hey Tom, thanks for the bug report! Are you totally certain the bug does not exist with type 42 sans-serif fonts? Because I also have a weird letter spacing with those fonts, as well as with the serif ones. For example, import matplotlib as mpl
import matplotlib.pyplot as plt
plt.style.use('default')
for fam, ft in [('sans', 3), ('sans', 42), ('serif', 3), ('serif', 42)]:
plt.rcParams['pdf.fonttype'] = ft # in {3, 42}
plt.rcParams['font.family'] = fam # in {'serif', 'sans'}
plt.rcParams['font.size'] = 20
fig_label = "{fam}_T{ft}".format(fam=plt.rcParams['font.family'][0],
ft=plt.rcParams['pdf.fonttype'])
fig, ax = plt.subplots(num=fig_label)
ax.plot([0, 1])
ax.set_xlabel("mpl " + mpl.__version__, fontsize=10)
ax.set_title("This is the title")
fig.savefig(fig.get_label() + ".pdf") produces weird outputs with both type 42 font families Setup: |
Indeed you are right, the weird spacing happens also with sans-serif font, I overlooked this test. |
I wonder if the weird spacing with type 42 fonts isn't a bigger issue than first thought. Running import matplotlib as mpl
import matplotlib.pyplot as plt
def plot_font_grade(family, fonttype):
plt.style.use('default') # just to be sure
plt.rcParams['pdf.fonttype'] = fonttype # in {3, 42}
plt.rcParams['font.family'] = family # in {'serif', 'sans'}
fig_label = "{fam}_T{ft}_grade".format(fam=plt.rcParams['font.family'][0],
ft=plt.rcParams['pdf.fonttype'])
fig, ax = plt.subplots(num=fig_label, figsize=(6.4, 12.4))
# Cosmeticks & version info
ax.set_xlabel("mpl " + mpl.__version__, fontsize=10)
ax.xaxis.set_major_locator(plt.NullLocator())
ax.yaxis.set_major_locator(plt.NullLocator())
ax.set_ylim(-10, 600)
# Plot text with bigger and bigger size
for i, fs in enumerate(range(4, 50, 2)):
ax.text(0.1, i*30, "{fs} pt font size".format(fs=fs), fontsize=fs)
fig.savefig(fig.get_label() + ".pdf")
plt.close(fig)
if __name__ == "__main__":
for fam, ft in [('sans', 3), ('sans', 42), ('serif', 3), ('serif', 42)]:
plot_font_grade(fam, ft) results in : |
Bisect:
Seems innocuous from the title... |
Editing def get_font(*args, **kwargs):
return ft2font.FT2Font(*args, **kwargs) fixes the problem, so indeed the cache is not quite right. |
This fixes the test case too: diff --git a/lib/matplotlib/backends/backend_pdf.py b/lib/matplotlib/backends/backend_pdf.py
index a5e6253ca..c293fea7c 100644
--- a/lib/matplotlib/backends/backend_pdf.py
+++ b/lib/matplotlib/backends/backend_pdf.py
@@ -41,6 +41,7 @@ from matplotlib.font_manager import findfont, is_opentype_cff_font, get_font
from matplotlib.afm import AFM
import matplotlib.type1font as type1font
import matplotlib.dviread as dviread
+from matplotlib.ft2font import FT2Font
from matplotlib.ft2font import (FIXED_WIDTH, ITALIC, LOAD_NO_SCALE,
LOAD_NO_HINTING, KERNING_UNFITTED)
from matplotlib.mathtext import MathTextParser
@@ -853,7 +854,7 @@ end"""
def embedTTF(self, filename, characters):
"""Embed the TTF font from the named file into the document."""
- font = get_font(filename)
+ font = FT2Font(filename)
fonttype = rcParams['pdf.fonttype']
def cvt(length, upe=font.units_per_EM, nearest=True): |
Adapted from the code samples in matplotlib#7937 by @TomDLT and @afvincent.
Adapted from the code samples in matplotlib#7937 by @TomDLT and @afvincent.
Closed by #7961 |
Glad to see this is fixed. I just ran into the same funny spacing, and spent 30 min tracking it back to Type 42 fonts. |
I wonder if this could be considered serious enough to trigger the release of a 2.0.1 version of matplotlib as soon as possible, since this issue prevents upgrading from the 1.5 branch whenever you use matplotlib to prepare illustrations that need to obey some editorial flow (being in PDF, using certain fonts). |
I believe there are plans to release a version 2.0.1, but no
specific date.
|
For what it's worth, I like to use type 42 fonts, but I can handle type 3 fonts. All the fonts I use come in a type 42 and type 3 version. Type 3 fonts are not editable if you import a pdf into Adobe Illustrator (or similar vector graphics programs), while type 42 fonts are editable. Matplotlib, however, creates a separate text box for every individual letter when type 42 fonts are employed. This makes it a pain to edit any word longer than one letter, so type 3 fonts are not much of a downgrade. I thought I remembered a proposal to fix matplotlib's breaking up a word into multiple text boxes, but I cannot find it anywhere. |
Yeah, matplotlib used to not break up the text into individual characters.
That was changed about 5 or so years ago. I don't remember the details
exactly, but the idea was that it was causing the output files to get very
big because the entire font package would have to get packaged into the
file if they were to be truly editable. Another aspect, IIRC, was that the
font package would have to be saved with the file because recipients of the
PDF may not have the font already installed, so they couldn't view the
file. Therefore, by switching to recording the individual glyphs, you save
on size and you guarantee that recipients can view your file as you
intended it.
I would be open to making this behavior switchable, though.
…On Wed, Mar 22, 2017 at 9:52 AM, Benjamin Reedlunn ***@***.*** > wrote:
For what it's worth, I like to use type 42 fonts, but I can handle type 3
fonts. All the fonts I use come in a type 42 and type 3 version. Type 3
fonts are not editable if you import a pdf into Adobe Illustrator (or
similar vector graphics programs), while type 42 fonts are editable.
Matplotlib, however, creates a separate text box for every individual
letter when type 42 fonts are employed. This makes it a pain to edit any
word longer than one letter, so type 3 fonts are not much of a downgrade. I
thought I remembered a proposal to fix matplotlib's breaking up a word into
multiple text boxes, but I cannot find it anywhere.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#7937 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AARy-KpBVfd0Sjhvzrl48Tw0urafAi4Rks5roSetgaJpZM4LsbdA>
.
|
The behavior is switchable. Use the |
I'm on a linux machine (Ubuntu 16.10) where matplotlib seems to invariably pick fonts (or the font version) that show the issue. As a matter of fact, matplotlib 2.0 seems to have other font nuisances too here, like picking by default a sans serif font for math expressions in $...$. It is unclear to me how to assure that matplotlib prefers a type 3 font when the type 42 is also present. |
@mdboom Last I checked, @WeatherGod I had not considered the file size issue with including the entire font package with the pdf. I like the idea of making it a rcParam, though. |
The release is very soon. |
Bug summary
Large TrueType
seriffont does not render correctly when saving in .pdfInterestingly, the bug does not happen when:
using sans-serif fontCode for reproduction
Actual outcome
save_42.pdf
Expected outcome
save_3.pdf
Matplotlib version
Matplotlib 2.0.0 installed with conda (same behavior with pip)
System version
Linux-3.16.0-4-amd64-x86_64-with-debian-8.7
Python 3.5.2 |Continuum Analytics, Inc.| (default, Jul 2 2016, 17:53:06)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)]
The text was updated successfully, but these errors were encountered: