Skip to content

feat(mathtext): support underline#23616

Open
tfpf wants to merge 6 commits intomatplotlib:mainfrom
tfpf:underline
Open

feat(mathtext): support underline#23616
tfpf wants to merge 6 commits intomatplotlib:mainfrom
tfpf:underline

Conversation

@tfpf
Copy link
Copy Markdown
Contributor

@tfpf tfpf commented Aug 14, 2022

PR Summary

#15624 hasn't seen any activity for a while, so I went ahead with this.

Note that the underline is drawn below the lowest descender. This is consistent with TeX. (The PNG images suffer from what I assume is pixel rounding.)

Fixes #14235.
Closes #15624

PR Checklist

Tests and Styling

  • Has pytest style unit tests (and pytest passes).
  • Is Flake 8 compliant (install flake8-docstrings and run flake8 --docstring-convention=all).

Documentation

  • New features are documented, with examples if plot related.
  • New features have an entry in doc/users/next_whats_new/ (follow instructions in README.rst there).
  • [N/A] API changes documented in doc/api/next_api_changes/ (follow instructions in README.rst there).
  • Documentation is sphinx and numpydoc compliant (the docs should build without error).

@tfpf tfpf marked this pull request as ready for review August 14, 2022 13:06
@oscargus
Copy link
Copy Markdown
Member

Looks good! I think it makes sense to add a brief What's new for this to make users aware that it is added.

Also, I think it may be enough to have a "lightweight" test for this as it doesn't seem very dependent on the font:

# 'lightweight' tests test only a single fontset (dejavusans, which is the
# default) and only png outputs, in order to minimize the size of baseline
# images.
lightweight_math_tests = [
r'$\sqrt[ab]{123}$', # github issue #8665
r'$x \overset{f}{\rightarrow} \overset{f}{x} \underset{xx}{ff} \overset{xx}{ff} \underset{f}{x} \underset{f}{\leftarrow} x$', # github issue #18241
r'$\sum x\quad\sum^nx\quad\sum_nx\quad\sum_n^nx\quad\prod x\quad\prod^nx\quad\prod_nx\quad\prod_n^nx$', # GitHub issue 18085
r'$1.$ $2.$ $19680801.$ $a.$ $b.$ $mpl.$',
]

@timhoffm timhoffm requested a review from anntzer August 15, 2022 08:04
@timhoffm
Copy link
Copy Markdown
Member

@anntzer I think you as our TeX expert should review this.

@anntzer
Copy link
Copy Markdown
Contributor

anntzer commented Aug 15, 2022

Sure, l'll need a couple of days though.

@anntzer
Copy link
Copy Markdown
Contributor

anntzer commented Aug 18, 2022

This seems reasonable, but 1) do you know why the overline() implementation is so different, using a fill instead? (which seems inconsistent with the TeXbook); 2) the TeXbook (rules G9/G10 p443) add an extra thickness of whitespace clearance over the overline / under the underline; do you know why they are not needed here (if they indeed aren't)?

@tfpf
Copy link
Copy Markdown
Contributor Author

tfpf commented Aug 20, 2022

the TeXbook (rules G9/G10 p443) add an extra thickness of whitespace clearance over the overline / under the underline

I think that extra space is used to set the minimum leading.

more_leading
If the leading is high, the vertical distance between the tops of the Ts and the underscores on the previous lines remains unchanged even if the underscores are underlined. (As if the underline wasn't there at all.)

less_leading
Upon reducing the leading, the Ts remain some distance away from the underline. It's like the underline forces the next line to go lower if it is too close.

I have not looked through Mathtext's leading rules, but it certainly looks like it's better to follow what TeX does. I will update this. Getting second thoughts about this now. Should I add that space at the bottom, or leave this as it is?

do you know why the overline() implementation is so different, using a fill instead

That's a good question, one which I wondered myself, but couldn't figure out. In fact, I haven't completely understood how glue works in Mathtext.

@QuLogic
Copy link
Copy Markdown
Member

QuLogic commented Mar 11, 2026

Could the differences have to do with the rule being incorrectly rendered inverted? #31046 (comment)

@tfpf tfpf changed the title Support \underline in Mathtext. feat(mathtext): support underline Apr 11, 2026
@tfpf
Copy link
Copy Markdown
Contributor Author

tfpf commented Apr 11, 2026

As pointed out by QuLogic and anntzer, the rendering issue is now resolved. Time to bring this back.😴

Preliminary Check

import string

import matplotlib.pyplot as plt

plt.rcdefaults()

fig, ax = plt.subplots(figsize=(20, 5))
ax.text(
    .5, .5, " ".join(f"${c}\\underline{{{c}}}$" for c in string.ascii_lowercase),
    size=30, ha="center", va="baseline",
)
ax.axhline(.5)
fig.savefig("underline.png")
fig.savefig("underline.svg")
plt.show()

The underlines are drawn as described in TEX: The Program. Thus, text with descenders will push the underline lower. This is the expected behaviour; see exercise 18.26 on page 178 of The TeXbook.

underline.png underline.svg

Caveats

  • The lines under 'e' and 'f' are not aligned because their lowermost points aren't aligned. (This will be font-specific.)

@tfpf
Copy link
Copy Markdown
Contributor Author

tfpf commented Apr 11, 2026

do you know why the overline() implementation is so different, using a fill instead? (which seems inconsistent with the TeXbook)

I can make a guess.

The line above the body of a radical must touch the top of the radical (a tick mark), so it is imperative that the line be rendered at the correct height. This combined with the fact that the text under radicals (and overlines) is supposed to be rendered in cramped style might explain why the space between it and the body was not calculated but filled up with stretchable glue. You can see this in the sqrt function. That logic appears to have been reused for overline.

the TeXbook (rules G9/G10 p443) add an extra thickness of whitespace clearance over the overline / under the underline; do you know why they are not needed here (if they indeed aren't)?

I am now fairly sure that this was done to give the line some space between it and the previous or next lines. I suppose the same could be done here, but it is not clear why he set the depth directly instead of adding a vertical space.

@tfpf tfpf marked this pull request as ready for review April 12, 2026 11:30
@QuLogic
Copy link
Copy Markdown
Member

QuLogic commented Apr 17, 2026

Comparing with usetex=True, this does look pretty consistent with LaTeX, though it seems our rule thickness is a bit bigger (and so the gap is bigger).

But the inconsistency with the underline thickness does make me wonder if we should disable snapping on all mathtext boxes. Any thoughts @anntzer @tacaswell? Unfortunately, this would cause about 120 test image changes.

Copy link
Copy Markdown
Member

@QuLogic QuLogic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is good otherwise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add \underline to mathtext?

5 participants