Skip to content

Font "DejaVu Sans" can only be used through fallback #11077

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
nigiord opened this issue Apr 18, 2018 · 12 comments
Closed

Font "DejaVu Sans" can only be used through fallback #11077

nigiord opened this issue Apr 18, 2018 · 12 comments
Labels
status: needs clarification Issues that need more information to resolve. topic: text
Milestone

Comments

@nigiord
Copy link

nigiord commented Apr 18, 2018

Bug report

Bug summary

When rcParams['font.family'] is set to 'sans-serif', matplotlib correctly fallback to 'DejaVu Sans' (a warning is displayed and the "DejaVu Sans" font is plotted). However when rcParams['font.family'] is directly set to 'DejaVu Sans', matplotlib seems to use another font without warning.

Code for reproduction

import matplotlib as mpl
import matplotlib.pyplot as plt

mpl.rcParams['font.family'] = 'sans-serif'
fig, ax = plt.subplots(figsize=(1,1))
ax.set_title('no serif here as expected')
plt.show()
print(ax.title.get_font_properties().get_fontconfig_pattern())


mpl.rcParams['font.family'] = 'DejaVu Sans'
fig, ax = plt.subplots(figsize=(1,1))
ax.set_title('serif here as not expected')
plt.show()
print(ax.title.get_font_properties().get_fontconfig_pattern())

Actual outcome

matplotlib_bug

Expected outcome

I would expect the font to be "DejaVu Sans" in both cases (i.e. without serif in both cases). It is possible that the warning message is, in fact, incorrect. But I can't find a way to display the font that is currently displayed on the graph.

Matplotlib version

  • Operating system: Debian 10 (Buster, Testing)
  • Matplotlib version: 2.2.2
  • Matplotlib backend (print(matplotlib.get_backend())): TkAgg
  • Python version: 3.6.4
  • Jupyter version (if applicable): 4.4.0 (similar problem outside jupyter)

Matplotlib was installed through conda (conda-forge channel).

Thank you.

@anntzer
Copy link
Contributor

anntzer commented Apr 24, 2018

Does rm ~/.cache/matplotlib/fontList.json help?

Probably related to #10245 (due to the presence of a conda env, I guess).

@tacaswell tacaswell added this to the v3.0 milestone Apr 24, 2018
@nigiord
Copy link
Author

nigiord commented Apr 25, 2018

Does rm ~/.cache/matplotlib/fontList.json help?

Nope, the problem is still here.

The problem is also present using a fresh virtualenv created with:

python3 -m venv mpltest
source mpltest/bin/activate
pip install matplotlib

@anntzer
Copy link
Contributor

anntzer commented Apr 25, 2018

Can you provide the contents of your fontList.json? (perhaps via gist.github.com or other gist service, as it can be quite long)

@nigiord
Copy link
Author

nigiord commented Apr 26, 2018

@anntzer
Copy link
Contributor

anntzer commented Apr 26, 2018

I can't reproduce this locally, even though I forced the use of your font cache.
If you're up for some print-debugging, I'd suggest stepping in at https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/font_manager.py#L1197 and see what are the relevant font-matching scores, especially when the correct font (DejaVu Sans) is being matched.

@nigiord
Copy link
Author

nigiord commented Apr 27, 2018

I do not know exactly what would be interesting to print, but this is what I tried.

I added this at line 1215:

        print(best_font.fname)
        print("Score:", best_score)
        print("Family:", self.score_family(prop.get_family(), best_font.name))
        print("Style:", self.score_style(prop.get_style(), best_font.style))
        print("Variant:", self.score_variant(prop.get_variant(), best_font.variant))
        print("Weight:", self.score_weight(prop.get_weight(), best_font.weight))
        print("Stretch:", self.score_stretch(prop.get_stretch(), best_font.stretch))
        print("Size:", self.score_size(prop.get_size(), best_font.size))
        print('findfont: Matching %s to %s (%s) with score of %f' %
              (prop, best_font.name, repr(best_font.fname), best_score))

Then I ran the following code:

import matplotlib as mpl
import matplotlib.pyplot as plt

mpl.rcParams['font.family'] = 'DejaVu Sans'
fig, ax = plt.subplots(figsize=(2,2))
ax.set_title('serif here as not expected', fontsize=20)
plt.show()

Output

/home/testuser/.virtualenvs/mpltest/lib/python3.6/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSans.ttf
Score: 0.05
Family: 0.0
Style: 0.0
Variant: 0.0
Weight: 0.05
Stretch: 0.0
Size: 0.0
findfont: Matching :family=DejaVu Sans:style=normal:variant=normal:weight=normal:stretch=normal:size=20.0 to DejaVu Sans ('/home/testuser/.virtualenvs/mpltest/lib/python3.6/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSans.ttf') with score of 0.050000

But the displayed font is not correct:
mpl

It seems to me that the font is correctly chosen at this step, so the problem is probably elsewhere.

@anntzer
Copy link
Contributor

anntzer commented Apr 28, 2018

What happens if you edit backend_agg.py as follows:

diff --git a/lib/matplotlib/backends/backend_agg.py b/lib/matplotlib/backends/backend_agg.py
index bf4b85032..7cf1d7b8e 100644
--- a/lib/matplotlib/backends/backend_agg.py
+++ b/lib/matplotlib/backends/backend_agg.py
@@ -267,6 +267,7 @@ class RendererAgg(RendererBase):
         """
         fname = findfont(prop)
         font = get_font(fname)
+        print(prop, fname, font)
 
         font.clear()
         size = prop.get_size_in_points()

?

@nigiord
Copy link
Author

nigiord commented May 2, 2018

>>> import matplotlib as mpl
>>> import matplotlib.pyplot as plt
>>> 
>>> mpl.rcParams['font.family'] = 'DejaVu Sans'
>>> fig, ax = plt.subplots(figsize=(2,2))
>>> ax.set_title('serif here as not expected', fontsize=20)
Text(0.5,1,'serif here as not expected')
>>> plt.show()

Output
Same as above with the following additional output:

:family=DejaVu Sans:style=normal:variant=normal:weight=normal:stretch=normal:size=8.0 /home/testuser/.virtualenvs/mpltest/lib/python3.6/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSans.ttf <matplotlib.ft2font.FT2Font object at 0x7fc72557e780>
:family=DejaVu Sans:style=normal:variant=normal:weight=normal:stretch=normal:size=8.0 /home/testuser/.virtualenvs/mpltest/lib/python3.6/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSans.ttf <matplotlib.ft2font.FT2Font object at 0x7fc72557e780>
:family=DejaVu Sans:style=normal:variant=normal:weight=normal:stretch=normal:size=8.0 /home/testuser/.virtualenvs/mpltest/lib/python3.6/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSans.ttf <matplotlib.ft2font.FT2Font object at 0x7fc72557e780>
:family=DejaVu Sans:style=normal:variant=normal:weight=normal:stretch=normal:size=8.0 /home/testuser/.virtualenvs/mpltest/lib/python3.6/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSans.ttf <matplotlib.ft2font.FT2Font object at 0x7fc72557e780>
:family=DejaVu Sans:style=normal:variant=normal:weight=normal:stretch=normal:size=8.0 /home/testuser/.virtualenvs/mpltest/lib/python3.6/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSans.ttf <matplotlib.ft2font.FT2Font object at 0x7fc72557e780>
:family=DejaVu Sans:style=normal:variant=normal:weight=normal:stretch=normal:size=8.0 /home/testuser/.virtualenvs/mpltest/lib/python3.6/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSans.ttf <matplotlib.ft2font.FT2Font object at 0x7fc72557e780>
:family=DejaVu Sans:style=normal:variant=normal:weight=normal:stretch=normal:size=8.0 /home/testuser/.virtualenvs/mpltest/lib/python3.6/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSans.ttf <matplotlib.ft2font.FT2Font object at 0x7fc72557e780>
:family=DejaVu Sans:style=normal:variant=normal:weight=normal:stretch=normal:size=8.0 /home/testuser/.virtualenvs/mpltest/lib/python3.6/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSans.ttf <matplotlib.ft2font.FT2Font object at 0x7fc72557e780>
:family=DejaVu Sans:style=normal:variant=normal:weight=normal:stretch=normal:size=8.0 /home/testuser/.virtualenvs/mpltest/lib/python3.6/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSans.ttf <matplotlib.ft2font.FT2Font object at 0x7fc72557e780>
:family=DejaVu Sans:style=normal:variant=normal:weight=normal:stretch=normal:size=8.0 /home/testuser/.virtualenvs/mpltest/lib/python3.6/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSans.ttf <matplotlib.ft2font.FT2Font object at 0x7fc72557e780>
:family=DejaVu Sans:style=normal:variant=normal:weight=normal:stretch=normal:size=8.0 /home/testuser/.virtualenvs/mpltest/lib/python3.6/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSans.ttf <matplotlib.ft2font.FT2Font object at 0x7fc72557e780>
:family=DejaVu Sans:style=normal:variant=normal:weight=normal:stretch=normal:size=20.0 /home/testuser/.virtualenvs/mpltest/lib/python3.6/site-packages/matplotlib/mpl-data/fonts/ttf/DejaVuSans.ttf <matplotlib.ft2font.FT2Font object at 0x7fc72557e780>

@anntzer anntzer added the status: needs clarification Issues that need more information to resolve. label May 23, 2018
@nigiord
Copy link
Author

nigiord commented May 23, 2018

I noticed that if I set font.sans-serif (instead of font.family) to "DejaVu Sans", the warning disappears and the font is correct.

Input

import matplotlib as mpl
import matplotlib.pyplot as plt

mpl.rcParams['font.family'] = 'sans-serif'
mpl.rcParams['font.sans-serif'] = 'DejaVu Sans'

fig, ax = plt.subplots(figsize=(1,1))
ax.set_title('no serif here as expected')
plt.show()
print(ax.title.get_font_properties().get_fontconfig_pattern())

Output

capture d ecran_2018-05-23_10-31-16

It makes me think that "DejaVu Sans" is not a valid font.family name. The warning and the absence of error message misled me to think otherwise.

If "DejaVu Sans" is truly not acceptable as a font.family value, I think matplotlib should display something in the second case described in the original post of this issue. I still do not understand why it silently uses a serif font.

@anntzer
Copy link
Contributor

anntzer commented May 24, 2018

Well, as I mentioned earlier specifying "DejaVu Sans" for font.family does work for me and should work.
What happens if you try some other font present on your system such as "DejaVu Sans Mono" or whatever you can think of?

@nigiord
Copy link
Author

nigiord commented May 24, 2018

Ok I think I got it, truly sorry if you lost time on this. The font I have been actually seeing this whole time was the default LateX font. With text.usetex set to False, the chosen font.family is properly displayed.

Example:

import matplotlib as mpl
import matplotlib.pyplot as plt

mpl.rcParams['text.usetex'] = False
mpl.rcParams['font.family'] = 'DejaVu Sans'
fig, ax = plt.subplots(figsize=(1,1))
ax.set_title('sans serif here')
plt.show()
print(ax.title.get_font_properties().get_fontconfig_pattern())

capture d ecran_2018-05-24_15-33-08

With mpl.rcParams['text.usetex'] = True I always have the LateX font, whatever the font.family I choose, EXCEPT if font.family is set to sans-serif.

According to the comment in matplotlibrc, only a subset of fonts are supported with text.usetex set to True:

### LaTeX customizations. See http://www.scipy.org/Wiki/Cookbook/Matplotlib/UsingTex
text.usetex         : True  # use latex for all text handling. The following fonts
                              # are supported through the usual rc parameter settings:
                              # new century schoolbook, bookman, times, palatino,
                              # zapf chancery, charter, serif, sans-serif, helvetica,
                              # avant garde, courier, monospace, computer modern roman,
                              # computer modern sans serif, computer modern typewriter
                              # If another font is desired which can loaded using the
                              # LaTeX \usepackage command, please inquire at the
                              # matplotlib mailing list

sans-serif is in this list, but not DejaVu Sans. I suppose matplotlib silently falls back to the default LateX font if the defined font.family is not compatible with text.usetex.

@jklymak
Copy link
Member

jklymak commented May 24, 2018

OK, glad its working for you...

@jklymak jklymak closed this as completed May 24, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: needs clarification Issues that need more information to resolve. topic: text
Projects
None yet
Development

No branches or pull requests

4 participants