From f259bf821b6d2c486965d8ba26784415d252f429 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Sat, 10 Jul 2021 04:58:46 -0400 Subject: [PATCH 1/4] Add fontsize option to mathmpl Sphinx extension. And set it to 11 points, which matches the new theme. --- doc/conf.py | 1 + lib/matplotlib/sphinxext/mathmpl.py | 24 ++++++++++++++++-------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index b77413ab4735..cf46047ea4a8 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -178,6 +178,7 @@ def _check_dependencies(): } plot_gallery = 'True' +mathmpl_fontsize = 11.0 # Monkey-patching gallery signature to include search keywords gen_rst.SPHX_GLR_SIG = """\n diff --git a/lib/matplotlib/sphinxext/mathmpl.py b/lib/matplotlib/sphinxext/mathmpl.py index b86d0e841c53..55d7f4b95265 100644 --- a/lib/matplotlib/sphinxext/mathmpl.py +++ b/lib/matplotlib/sphinxext/mathmpl.py @@ -7,6 +7,7 @@ import matplotlib as mpl from matplotlib import _api, mathtext +from matplotlib.rcsetup import validate_float_or_None # Define LaTeX math node: @@ -25,8 +26,11 @@ def math_role(role, rawtext, text, lineno, inliner, node = latex_math(rawtext) node['latex'] = latex node['fontset'] = options.get('fontset', 'cm') + node['fontsize'] = options.get('fontsize', + setup.app.config.mathmpl_fontsize) return [node], [] -math_role.options = {'fontset': fontset_choice} +math_role.options = {'fontset': fontset_choice, + 'fontsize': validate_float_or_None} class MathDirective(Directive): @@ -34,23 +38,25 @@ class MathDirective(Directive): required_arguments = 0 optional_arguments = 0 final_argument_whitespace = False - option_spec = {'fontset': fontset_choice} + option_spec = {'fontset': fontset_choice, + 'fontsize': validate_float_or_None} def run(self): latex = ''.join(self.content) node = latex_math(self.block_text) node['latex'] = latex node['fontset'] = self.options.get('fontset', 'cm') + node['fontsize'] = self.options.get('fontsize', + setup.app.config.mathmpl_fontsize) return [node] # This uses mathtext to render the expression -def latex2png(latex, filename, fontset='cm'): - latex = "$%s$" % latex - with mpl.rc_context({'mathtext.fontset': fontset}): +def latex2png(latex, filename, fontset='cm', fontsize=10): + with mpl.rc_context({'mathtext.fontset': fontset, 'font.size': fontsize}): try: depth = mathtext.math_to_image( - latex, filename, dpi=100, format="png") + f"${latex}$", filename, dpi=100, format="png") except Exception: _api.warn_external(f"Could not render math expression {latex}") depth = 0 @@ -62,14 +68,15 @@ def latex2html(node, source): inline = isinstance(node.parent, nodes.TextElement) latex = node['latex'] fontset = node['fontset'] + fontsize = node['fontsize'] name = 'math-{}'.format( - hashlib.md5((latex + fontset).encode()).hexdigest()[-10:]) + hashlib.md5(f'{latex}{fontset}{fontsize}'.encode()).hexdigest()[-10:]) destdir = Path(setup.app.builder.outdir, '_images', 'mathmpl') destdir.mkdir(parents=True, exist_ok=True) dest = destdir / f'{name}.png' - depth = latex2png(latex, dest, fontset) + depth = latex2png(latex, dest, fontset, fontsize=fontsize) if inline: cls = '' @@ -86,6 +93,7 @@ def latex2html(node, source): def setup(app): setup.app = app + app.add_config_value('mathmpl_fontsize', 10.0, True) # Add visit/depart methods to HTML-Translator: def visit_latex_math_html(self, node): From 3b7342c839fbddd73fc4f841d5481ef77f286cef Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Fri, 16 Jul 2021 17:40:48 -0400 Subject: [PATCH 2/4] Add srcset support to mathmpl sphinx extension. And set it to include 2x in our docs, like with sphinx gallery. --- doc/conf.py | 1 + lib/matplotlib/sphinxext/mathmpl.py | 43 ++++++++++++++++++++++++++--- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index cf46047ea4a8..52b3145c38c0 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -179,6 +179,7 @@ def _check_dependencies(): plot_gallery = 'True' mathmpl_fontsize = 11.0 +mathmpl_srcset = ['2x'] # Monkey-patching gallery signature to include search keywords gen_rst.SPHX_GLR_SIG = """\n diff --git a/lib/matplotlib/sphinxext/mathmpl.py b/lib/matplotlib/sphinxext/mathmpl.py index 55d7f4b95265..7b6c87106f49 100644 --- a/lib/matplotlib/sphinxext/mathmpl.py +++ b/lib/matplotlib/sphinxext/mathmpl.py @@ -4,6 +4,7 @@ from docutils import nodes from docutils.parsers.rst import Directive, directives import sphinx +from sphinx.errors import ConfigError, ExtensionError import matplotlib as mpl from matplotlib import _api, mathtext @@ -52,11 +53,11 @@ def run(self): # This uses mathtext to render the expression -def latex2png(latex, filename, fontset='cm', fontsize=10): +def latex2png(latex, filename, fontset='cm', fontsize=10, dpi=100): with mpl.rc_context({'mathtext.fontset': fontset, 'font.size': fontsize}): try: depth = mathtext.math_to_image( - f"${latex}$", filename, dpi=100, format="png") + f"${latex}$", filename, dpi=dpi, format="png") except Exception: _api.warn_external(f"Could not render math expression {latex}") depth = 0 @@ -74,10 +75,21 @@ def latex2html(node, source): destdir = Path(setup.app.builder.outdir, '_images', 'mathmpl') destdir.mkdir(parents=True, exist_ok=True) - dest = destdir / f'{name}.png' + dest = destdir / f'{name}.png' depth = latex2png(latex, dest, fontset, fontsize=fontsize) + srcset = [] + for size in setup.app.config.mathmpl_srcset: + filename = f'{name}-{size.replace(".", "_")}.png' + latex2png(latex, destdir / filename, fontset, fontsize=fontsize, + dpi=100 * float(size[:-1])) + srcset.append( + f'{setup.app.builder.imgpath}/mathmpl/{filename} {size}') + if srcset: + srcset = (f'srcset="{setup.app.builder.imgpath}/mathmpl/{name}.png, ' + + ', '.join(srcset) + '" ') + if inline: cls = '' else: @@ -88,12 +100,35 @@ def latex2html(node, source): style = '' return (f'') + f' {srcset}{cls}{style}/>') + + +def _config_inited(app, config): + # Check for srcset hidpi images + for i, size in enumerate(app.config.mathmpl_srcset): + if size[-1] == 'x': # "2x" = "2.0" + try: + float(size[:-1]) + except ValueError: + raise ConfigError( + f'Invalid value for mathmpl_srcset parameter: {size!r}. ' + 'Must be a list of strings with the multiplicative ' + 'factor followed by an "x". e.g. ["2.0x", "1.5x"]') + else: + raise ConfigError( + f'Invalid value for mathmpl_srcset parameter: {size!r}. ' + 'Must be a list of strings with the multiplicative ' + 'factor followed by an "x". e.g. ["2.0x", "1.5x"]') def setup(app): setup.app = app app.add_config_value('mathmpl_fontsize', 10.0, True) + app.add_config_value('mathmpl_srcset', [], True) + try: + app.connect('config-inited', _config_inited) # Sphinx 1.8+ + except ExtensionError: + app.connect('env-updated', lambda app, env: _config_inited(app, None)) # Add visit/depart methods to HTML-Translator: def visit_latex_math_html(self, node): From 654967bab60adbe99fda45911c51ea7a3b84eb22 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Fri, 16 Jul 2021 19:14:22 -0400 Subject: [PATCH 3/4] Add docs about new mathmpl options. --- doc/users/next_whats_new/mathmpl_hidpi.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 doc/users/next_whats_new/mathmpl_hidpi.rst diff --git a/doc/users/next_whats_new/mathmpl_hidpi.rst b/doc/users/next_whats_new/mathmpl_hidpi.rst new file mode 100644 index 000000000000..e90708d5e35d --- /dev/null +++ b/doc/users/next_whats_new/mathmpl_hidpi.rst @@ -0,0 +1,13 @@ +More configuration of ``mathmpl:`` sphinx extension +--------------------------------------------------- + +The `matplotlib.sphinxext.mathmpl` sphinx extension supports two new +configuration options that may be specified in your ``conf.py``: + +- ``mathmpl_fontsize`` (float), which sets the font size of the math text in + points; +- ``mathmpl_srcset`` (list of str), which provides a list of sizes to support + `responsive resolution images + `__ + The list should contain additional x-descriptors (``'1.5x'``, ``'2x'``, etc.) + to generate (1x is the default and always included.) From 7ac178e310c54f511166d764fc4ff51cdc68c623 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Tue, 27 Jul 2021 20:58:00 -0400 Subject: [PATCH 4/4] Document mathmpl Sphinx extension. --- doc/api/index.rst | 1 + doc/api/sphinxext_mathmpl_api.rst | 7 +++ lib/matplotlib/sphinxext/mathmpl.py | 68 +++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 doc/api/sphinxext_mathmpl_api.rst diff --git a/doc/api/index.rst b/doc/api/index.rst index 5a309fcfc9e4..d8b0bebee569 100644 --- a/doc/api/index.rst +++ b/doc/api/index.rst @@ -82,6 +82,7 @@ Alphabetical list of modules: rcsetup_api.rst sankey_api.rst scale_api.rst + sphinxext_mathmpl_api.rst sphinxext_plot_directive_api.rst spines_api.rst style_api.rst diff --git a/doc/api/sphinxext_mathmpl_api.rst b/doc/api/sphinxext_mathmpl_api.rst new file mode 100644 index 000000000000..839334ca39fe --- /dev/null +++ b/doc/api/sphinxext_mathmpl_api.rst @@ -0,0 +1,7 @@ +================================ +``matplotlib.sphinxext.mathmpl`` +================================ + +.. automodule:: matplotlib.sphinxext.mathmpl + :exclude-members: latex_math + :no-undoc-members: diff --git a/lib/matplotlib/sphinxext/mathmpl.py b/lib/matplotlib/sphinxext/mathmpl.py index 7b6c87106f49..dd30f34a8e66 100644 --- a/lib/matplotlib/sphinxext/mathmpl.py +++ b/lib/matplotlib/sphinxext/mathmpl.py @@ -1,3 +1,68 @@ +r""" +A role and directive to display mathtext in Sphinx +================================================== + +.. warning:: + In most cases, you will likely want to use one of `Sphinx's builtin Math + extensions + `__ + instead of this one. + +Mathtext may be included in two ways: + +1. Inline, using the role:: + + This text uses inline math: :mathmpl:`\alpha > \beta`. + + which produces: + + This text uses inline math: :mathmpl:`\alpha > \beta`. + +2. Standalone, using the directive:: + + Here is some standalone math: + + .. mathmpl:: + + \alpha > \beta + + which produces: + + Here is some standalone math: + + .. mathmpl:: + + \alpha > \beta + +Options +------- + +The ``mathmpl`` role and directive both support the following options: + + fontset : str, default: 'cm' + The font set to use when displaying math. See :rc:`mathtext.fontset`. + + fontsize : float + The font size, in points. Defaults to the value from the extension + configuration option defined below. + +Configuration options +--------------------- + +The mathtext extension has the following configuration options: + + mathmpl_fontsize : float, default: 10.0 + Default font size, in points. + + mathmpl_srcset : list of str, default: [] + Additional image sizes to generate when embedding in HTML, to support + `responsive resolution images + `__. + The list should contain additional x-descriptors (``'1.5x'``, ``'2x'``, + etc.) to generate (1x is the default and always included.) + +""" + import hashlib from pathlib import Path @@ -35,6 +100,9 @@ def math_role(role, rawtext, text, lineno, inliner, class MathDirective(Directive): + """ + The ``.. mathmpl::`` directive, as documented in the module's docstring. + """ has_content = True required_arguments = 0 optional_arguments = 0