diff --git a/doc/release/next_whats_new/underline-23616.rst b/doc/release/next_whats_new/underline-23616.rst new file mode 100644 index 000000000000..184c588b842c --- /dev/null +++ b/doc/release/next_whats_new/underline-23616.rst @@ -0,0 +1,12 @@ +Underlining text while using Mathtext +------------------------------------- + +Mathtext now supports the ``\underline`` command. + +.. code-block:: python + + import matplotlib.pyplot as plt + + plt.text(0.4, 0.7, r'This is $\underline{underlined}$ text.') + plt.text(0.4, 0.3, r'So is $\underline{\mathrm{this}}$.') + plt.show() diff --git a/lib/matplotlib/_mathtext.py b/lib/matplotlib/_mathtext.py index 21ec24d73286..b04386e7666a 100644 --- a/lib/matplotlib/_mathtext.py +++ b/lib/matplotlib/_mathtext.py @@ -2207,6 +2207,8 @@ def csnames(group: str, names: Iterable[str]) -> Regex: p.overline = cmd(r"\overline", p.required_group("body")) + p.underline = cmd(r"\underline", p.required_group("body")) + p.overset = cmd( r"\overset", p.optional_group("annotation") + p.optional_group("body")) @@ -2259,6 +2261,7 @@ def csnames(group: str, names: Iterable[str]) -> Regex: | p.underset | p.sqrt | p.overline + | p.underline | p.text | p.boldsymbol | p.substack @@ -2945,6 +2948,21 @@ def overline(self, toks: ParseResults) -> T.Any: hlist = Hlist([rightside]) return [hlist] + def underline(self, toks: ParseResults) -> T.Any: + body = toks["body"] + state = self.get_state() + thickness = state.get_current_underline_thickness() + # Place the underline below `body` (node735). + vlist = Vlist([ + Hlist([body]), + Kern(3 * thickness), + Hrule(state, thickness), + ]) + delta = vlist.height + vlist.depth + thickness + vlist.height = body.height + vlist.depth = delta - vlist.height + return [Hlist([vlist])] + def _auto_sized_delimiter(self, front: str, middle: list[Box | Char | str], back: str) -> T.Any: diff --git a/lib/matplotlib/tests/baseline_images/test_mathtext/mathtext1_dejavusans_09.png b/lib/matplotlib/tests/baseline_images/test_mathtext/mathtext1_dejavusans_09.png new file mode 100644 index 000000000000..9d96e8eb87b9 Binary files /dev/null and b/lib/matplotlib/tests/baseline_images/test_mathtext/mathtext1_dejavusans_09.png differ diff --git a/lib/matplotlib/tests/test_mathtext.py b/lib/matplotlib/tests/test_mathtext.py index 33fb8918d22a..a8f9236b5208 100644 --- a/lib/matplotlib/tests/test_mathtext.py +++ b/lib/matplotlib/tests/test_mathtext.py @@ -154,6 +154,7 @@ r'$\left\lbrace\frac{\left\lbrack A^b_c\right\rbrace}{\left\leftbrace D^e_f \right\rbrack}\right\rightbrace\ \left\leftparen\max_{x} \left\lgroup \frac{A}{B}\right\rgroup \right\rightparen$', r'$\left( a\middle. b \right)$ $\left( \frac{a}{b} \middle\vert x_i \in P^S \right)$ $\left[ 1 - \middle| a\middle| + \left( x - \left\lfloor \dfrac{a}{b}\right\rfloor \right) \right]$', r'$\sum_{\substack{k = 1\\ k \neq \lfloor n/2\rfloor}}^{n}P(i,j) \sum_{\substack{i \neq 0\\ -1 \leq i \leq 3\\ 1 \leq j \leq 5}} F^i(x,y) \sum_{\substack{\left \lfloor \frac{n}{2} \right\rfloor}} F(n)$', + ' '.join(f'${c}\\underline{{{c}}}$' for c in 'abfghy') + r' $\underline{\left(\dfrac{num}{\underline{den}}\right)}^{\underline{p_1}}$', ] digits = "0123456789"