diff --git a/examples/text_labels_and_annotations/mathtext_fontfamily_example.py b/examples/text_labels_and_annotations/mathtext_fontfamily_example.py
new file mode 100644
index 000000000000..2b417cfcac91
--- /dev/null
+++ b/examples/text_labels_and_annotations/mathtext_fontfamily_example.py
@@ -0,0 +1,37 @@
+"""
+===============
+Math fontfamily
+===============
+
+A simple example showcasing the new *math_fontfamily* parameter that can
+be used to change the family of fonts for each individual text
+element in a plot.
+
+If no parameter is set, the global value
+:rc:`mathtext.fontset` will be used.
+"""
+
+import matplotlib.pyplot as plt
+
+plt.figure(figsize=(6, 5))
+
+# A simple plot for the background.
+plt.plot(range(11), color="0.9")
+
+# A text mixing normal text and math text.
+msg = (r"Normal Text. $Text\ in\ math\ mode:\ "
+ r"\int_{0}^{\infty } x^2 dx$")
+
+# Set the text in the plot.
+plt.text(1, 7, msg, size=12, math_fontfamily='cm')
+
+# Set another font for the next text.
+plt.text(1, 3, msg, size=12, math_fontfamily='dejavuserif')
+
+# *math_fontfamily* can be used in most places where there is text,
+# like in the title:
+plt.title(r"$Title\ in\ math\ mode:\ \int_{0}^{\infty } x^2 dx$",
+ math_fontfamily='stixsans', size=14)
+
+# Note that the normal text is not changed by *math_fontfamily*.
+plt.show()
diff --git a/lib/matplotlib/font_manager.py b/lib/matplotlib/font_manager.py
index 5952b8bd190c..5769d6d33fe0 100644
--- a/lib/matplotlib/font_manager.py
+++ b/lib/matplotlib/font_manager.py
@@ -41,6 +41,7 @@
from matplotlib import afm, cbook, ft2font, rcParams
from matplotlib.fontconfig_pattern import (
parse_fontconfig_pattern, generate_fontconfig_pattern)
+from matplotlib.rcsetup import _validators
_log = logging.getLogger(__name__)
@@ -624,10 +625,10 @@ class FontProperties:
"""
A class for storing and manipulating font properties.
- The font properties are those described in the `W3C Cascading
- Style Sheet, Level 1
+ The font properties are the six properties described in the
+ `W3C Cascading Style Sheet, Level 1
`_ font
- specification. The six properties are:
+ specification and *math_fontfamily* for math fonts:
- family: A list of font names in decreasing order of priority.
The items may include a generic font family name, either
@@ -653,6 +654,12 @@ class FontProperties:
'small', 'medium', 'large', 'x-large', 'xx-large' or an
absolute font size, e.g., 12.
+ - math_fontfamily: The family of fonts used to render math text; overrides
+ :rc:`mathtext.fontset`. Supported values are the same as the ones
+ supported by :rc:`mathtext.fontset` ::
+
+ 'dejavusans', 'dejavuserif', 'cm', 'stix', 'stixsans' and 'custom'.
+
The default font property for TrueType fonts (as specified in the
default rcParams) is ::
@@ -690,6 +697,7 @@ def __init__(self,
stretch= None,
size = None,
fname = None, # if set, it's a hardcoded filename to use
+ math_fontfamily = None,
):
self._family = _normalize_font_family(rcParams['font.family'])
self._slant = rcParams['font.style']
@@ -698,6 +706,7 @@ def __init__(self,
self._stretch = rcParams['font.stretch']
self._size = rcParams['font.size']
self._file = None
+ self._math_fontfamily = None
if isinstance(family, str):
# Treat family as a fontconfig pattern if it is the only
@@ -714,6 +723,7 @@ def __init__(self,
self.set_stretch(stretch)
self.set_file(fname)
self.set_size(size)
+ self.set_math_fontfamily(math_fontfamily)
@classmethod
def _from_any(cls, arg):
@@ -745,7 +755,8 @@ def __hash__(self):
self.get_weight(),
self.get_stretch(),
self.get_size_in_points(),
- self.get_file())
+ self.get_file(),
+ self.get_math_fontfamily())
return hash(l)
def __eq__(self, other):
@@ -934,6 +945,45 @@ def set_fontconfig_pattern(self, pattern):
else:
getattr(self, "set_" + key)(val)
+ def get_math_fontfamily(self):
+ """
+ Return the name of the font family used for math text.
+
+ The default font is :rc:`mathtext.fontset`.
+ """
+ if self._math_fontfamily is None:
+ return rcParams['mathtext.fontset']
+ return self._math_fontfamily
+
+ def set_math_fontfamily(self, fontfamily):
+ """
+ Set the font family for text in math mode.
+
+ If not set explicitly, :rc:`mathtext.fontset` will be used.
+
+ Parameters
+ ----------
+ fontfamily : str
+ The name of the font family.
+
+ Available font families are defined in the
+ matplotlibrc.template file
+ :ref:`here `
+
+ See Also
+ --------
+ .text.Text.get_math_fontfamily
+ """
+ if fontfamily is None:
+ self._math_fontfamily = None
+ return
+
+ valid_fonts = _validators['mathtext.fontset'].valid.values()
+ # _check_in_list() Validates the parameter math_fontfamily as
+ # if it were passed to rcParams['mathtext.fontset']
+ cbook._check_in_list(valid_fonts, math_fontfamily=fontfamily)
+ self._math_fontfamily = fontfamily
+
def copy(self):
"""Return a copy of self."""
new = type(self)()
diff --git a/lib/matplotlib/mathtext.py b/lib/matplotlib/mathtext.py
index 8641a4416f41..8b9df7e19203 100644
--- a/lib/matplotlib/mathtext.py
+++ b/lib/matplotlib/mathtext.py
@@ -3351,12 +3351,10 @@ def parse(self, s, dpi=72, prop=None, *, _force_standard_ps_fonts=False):
# lru_cache can't decorate parse() directly because the ps.useafm and
# mathtext.fontset rcParams also affect the parse (e.g. by affecting
# the glyph metrics).
- return self._parse_cached(s, dpi, prop, _force_standard_ps_fonts,
- rcParams['mathtext.fontset'])
+ return self._parse_cached(s, dpi, prop, _force_standard_ps_fonts)
@functools.lru_cache(50)
- def _parse_cached(self, s, dpi, prop, force_standard_ps_fonts, fontset):
-
+ def _parse_cached(self, s, dpi, prop, force_standard_ps_fonts):
if prop is None:
prop = FontProperties()
@@ -3365,7 +3363,8 @@ def _parse_cached(self, s, dpi, prop, force_standard_ps_fonts, fontset):
else:
backend = self._backend_mapping[self._output]()
fontset_class = cbook._check_getitem(
- self._font_type_mapping, fontset=fontset)
+ self._font_type_mapping,
+ fontset=prop.get_math_fontfamily())
font_output = fontset_class(prop, backend)
fontsize = prop.get_size_in_points()
diff --git a/lib/matplotlib/tests/baseline_images/test_mathtext/math_fontfamily_image.png b/lib/matplotlib/tests/baseline_images/test_mathtext/math_fontfamily_image.png
new file mode 100644
index 000000000000..feb34b1793db
Binary files /dev/null and b/lib/matplotlib/tests/baseline_images/test_mathtext/math_fontfamily_image.png differ
diff --git a/lib/matplotlib/tests/test_mathtext.py b/lib/matplotlib/tests/test_mathtext.py
index 285841f7277b..1b4d3336f19e 100644
--- a/lib/matplotlib/tests/test_mathtext.py
+++ b/lib/matplotlib/tests/test_mathtext.py
@@ -364,3 +364,13 @@ def test_mathtext_to_png(tmpdir):
mt = mathtext.MathTextParser('bitmap')
mt.to_png(str(tmpdir.join('example.png')), '$x^2$')
mt.to_png(io.BytesIO(), '$x^2$')
+
+
+@image_comparison(baseline_images=['math_fontfamily_image.png'],
+ savefig_kwarg={'dpi': 40})
+def test_math_fontfamily():
+ fig = plt.figure(figsize=(10, 3))
+ fig.text(0.2, 0.7, r"$This\ text\ should\ have\ one\ font$",
+ size=24, math_fontfamily='dejavusans')
+ fig.text(0.2, 0.3, r"$This\ text\ should\ have\ another$",
+ size=24, math_fontfamily='stix')
diff --git a/lib/matplotlib/text.py b/lib/matplotlib/text.py
index 75ffafe1a0b3..a1d475c1b948 100644
--- a/lib/matplotlib/text.py
+++ b/lib/matplotlib/text.py
@@ -1061,6 +1061,40 @@ def set_fontsize(self, fontsize):
self._fontproperties.set_size(fontsize)
self.stale = True
+ def get_math_fontfamily(self):
+ """
+ Return the font family name for math text rendered by Matplotlib.
+
+ The default value is :rc:`mathtext.fontset`.
+
+ See Also
+ --------
+ set_math_fontfamily
+ """
+ return self._fontproperties.get_math_fontfamily()
+
+ def set_math_fontfamily(self, fontfamily):
+ """
+ Set the font family for math text rendered by Matplotlib.
+
+ This does only affect Matplotlib's own math renderer. It has no effect
+ when rendering with TeX (``usetex=True``).
+
+ Parameters
+ ----------
+ fontfamily : str
+ The name of the font family.
+
+ Available font families are defined in the
+ :ref:`matplotlibrc.template file
+ `.
+
+ See Also
+ --------
+ get_math_fontfamily
+ """
+ self._fontproperties.set_math_fontfamily(fontfamily)
+
def set_fontweight(self, weight):
"""
Set the font weight.