10000 star (*) symbol in text box cuts off bottom of text when saved · Issue #15313 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content

star (*) symbol in text box cuts off bottom of text when saved #15313

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

Open
christopherlovell opened this issue Sep 20, 2019 · 18 comments · May be fixed by #15339
Open

star (*) symbol in text box cuts off bottom of text when saved #15313

christopherlovell opened this issue Sep 20, 2019 · 18 comments · May be fixed by #15339

Comments

@christopherlovell
Copy link

Bug report

Bug summary

When using the star (*) symbol in a text box, it cuts off the bottom of the text when saved (savefig). This is only the case when usetex=False in rcParams.

Code for reproduction

import matplotlib
import matplotlib.pyplot as plt

from matplotlib import rc
rc('text', usetex=False)

fig, ax = plt.subplots(1,1)
ax.text(0.5, 0.5, '$S_{*} M^{ath}$ and some not math',
         transform=ax.transAxes)
plt.savefig('test1.png', bbox_inches='tight')

test2

You can see the bottom of the text box is cut off. Whereas this plots fine:

fig, ax = plt.subplots(1,1)
ax.text(0.5, 0.5, '$S_{ome} M^{ath}$ and some not math',
         transform=ax.transAxes)
plt.savefig('test1.png', bbox_inches='tight')

test1

Matplotlib version

  • Operating system: Unix
  • Matplotlib version: 3.1.1
  • Matplotlib backend (print(matplotlib.get_backend())): TkAgg
  • Python version: Python 3.6.8 (default, Apr 25 2019, 21:02:35)

matplotlib installed from pip

  • Other libraries:

cycler==0.10.0
kiwisolver==1.1.0
numpy==1.17.2
pyparsing==2.4.2
python-dateutil==2.8.0
six==1.12.0

@ImportanceOfBeingErnest
Copy link
Member
ImportanceOfBeingErnest commented Sep 20, 2019

The first figure is much larger than the second. How exactly are they produced?

When running the code I get
test1

@ImportanceOfBeingErnest ImportanceOfBeingErnest added the status: needs clarification Issues that need more information to resolve. label Sep 20, 2019
@jklymak
Copy link
Member
jklymak commented Sep 21, 2019

I can confirm this on my machine.

import matplotlib.pyplot as plt
fig, ax = plt.subplots(1,1)
ax.text(0.5, 0.5, '$S_{x} Math$',
         transform=ax.transAxes)
ax.text(0.5, 0.2, '$S_{*} Math$',
         transform=ax.transAxes)
ax.text(0.2, 0.35, '$S_{*} Math_{p}$',
         transform=ax.transAxes)
plt.savefig('test1.png', dpi=200)

test1

It looks like somehow the lower extent is being set by the subscript if there is one, and not the minimum of the subscript and the rest of the text. Note if you put a bigger subscript in, all is well.

@jklymak jklymak removed the status: needs clarification Issues that need more information to resolve. label Sep 21, 2019
@ImportanceOfBeingErnest
Copy link
Member

So what's the difference?
The font seems to be the same.
I'm using windows instead of linux.
Maybe version of freetype? (I have freetype 2.9.1 ha9979f8_1 here)

@ImportanceOfBeingErnest
Copy link
Member

Oh, it's the dpi. Would be good to state it explicitely in the code, because matplotlib's default dpi=100 works fine it seems.

@jklymak
Copy link
Member
jklymak commented Sep 21, 2019

I dunno. So far, $S Math$ has a height of 26, and descent of 2. $S_{*} Math$ has a height of 21.2 and descent of 2. So somehow the height is being miscalculated.

@jklymak
Copy link
Member
jklymak commented Sep 21, 2019

Not sure why it ends up OK for 100 dpi, but yes thats true. Is matplotlib's default really 100 dpi? Regardless, the font metrics are incorrect so thats probably the root of the problem

@jklymak
Copy link
Member
jklymak commented Sep 22, 2019

Interestingly, this gets worse and worse the higher the dpi:

1500 dpi:

offset

This is not a problem for pdf backend, so its just agg/png.

@ImportanceOfBeingErnest
Copy link
Member
ImportanceOfBeingErnest commented Sep 22, 2019

It seems that at this point

self.height + self.depth,

self.height is wrong. But I'm lost at that point.

Also, it's not only the height that's wrong, but in general the position,

image

maybe one is the consequence of the other though.

@anntzer
Copy link
Contributor
anntzer commented Sep 22, 2019

fwiw this doesn't happen with mplcairo either; I have some plan to just lift the mplcairo mathtext code to replace MathtextBackendAgg...

@ImportanceOfBeingErnest
Copy link
Member

Isn't it that Cairo can directly render the glyphs, while Agg needs a FTImage? How would you replace that? (Matplotlib's internal Cairo backends also work fine in this context here.)

@anntzer
Copy link
Contributor
anntzer commented Sep 22, 2019

It doesn't really matter whether the rendering is done directly or via FT2Image; I think the important point is to repro the logic of rounding fractional glyph positions.

@ImportanceOfBeingErnest
Copy link
Member

The issue here is unrelated to rounding. It seems to be in the logic that places the image. If you replace this line

(bbox[3] - bbox[1]) - orig_depth,

by

(bbox[3] - bbox[1]),

i.e. don't subtract the "original depth", the result will be

image

which shows the correct image for the text that does not go below the baseline. But somehow you need to account for the depth, or else the image where text does go below the baseline will be placed wrongly aligned.

@jklymak
Copy link
Member
jklymak commented Sep 23, 2019

So should it just be that oy is changed?

@ImportanceOfBeingErnest
Copy link
Member

I don't think so, because I wouldn't know which quantity to use to discriminate the two cases. But maybe someone else has an idea, in which case

this is the code to reproduce above images.
import matplotlib.pyplot as plt
plt.rcParams["font.size"] = 48
fig, ax = plt.subplots(1,1, figsize=(5.5,2.7), dpi=300)
fig.subplots_adjust(left=0, right=1)
ax.axis("off")
t4 = ax.text(0.05, 0.5, '$S l$', transform=ax.transAxes)
t3 = ax.text(0.25, 0.5, '$S_{x} l$', transform=ax.transAxes)
t1 = ax.text(0.5, 0.5, '$S_{°} l$', transform=ax.transAxes)
t2 = ax.text(0.75, 0.5, '$S_{*} l$', transform=ax.transAxes)

ax.axhline(0.5, color="gray", linewidth=0.4)
plt.savefig('test1.png')
plt.savefig('test1.pdf')
plt.show()

@jklymak
Copy link
Member
jklymak commented Sep 23, 2019

Yeah somehow the baseline has been set to the bottom of the subscript but I’ve not been able to track how that gets decided. Maybe in the image creation?

@jklymak
Copy link
Member
jklymak commented Sep 23, 2019

An unhelpful data point: this has been like this since at least 2.0. I have trouble compiling anything older....

@ImportanceOfBeingErnest
Copy link
Member

It was also present earlier, but in 1.x the default math font was computer modern, which puts the asterix below the baseline and hence one wouldn't have noticed.

@anntzer anntzer linked a pull request Sep 25, 2019 that will close this issue
6 tasks
@anntzer
Copy link
Contributor
anntzer commented Sep 25, 2019

See #15339 (still needs some work and description).

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

Successfully merging a pull request may close this issue.

6 participants
0