Skip to content
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

[ENH]: Faking a text's metrics to fix its alignment #28211

Open
anntzer opened this issue May 12, 2024 · 1 comment
Open

[ENH]: Faking a text's metrics to fix its alignment #28211

anntzer opened this issue May 12, 2024 · 1 comment

Comments

@anntzer
Copy link
Contributor

anntzer commented May 12, 2024

Problem

Sometimes, it would be useful if we could "fake" a text's metrics to pretend it has a different physical size than its real size. Consider for example the following example; pretend the two subfigures are actually two separate figures that I want to save an embed in a presentation on consecutive slides, so that the orange line shows up on the second one:

from pylab import *
fig = figure(layout="constrained")
sfs = fig.subfigures(2)
ax0 = sfs[0].add_subplot()
ax0.plot([1, 2], label="foo")
sfs[0].legend(loc="outside right upper")
ax1 = sfs[1].add_subplot()
ax1.plot([1, 2], label="foo")
ax1.plot([2, 1], label="a longer label")
sfs[1].legend(loc="outside right upper")
show()

Figure_1
As it is, doing an animation would result in everything moving around in a rather ugly manner.

Because I know a bit about the matplotlib text internals :-) I know how to temporarily patch matplotlib to fix this, the trick being to swap out the text when matplotlib is measuring its extents, but not when drawing it:

diff --git i/lib/matplotlib/text.py w/lib/matplotlib/text.py
index 40cd8c8cd6..a042555ac1 100644
--- i/lib/matplotlib/text.py
+++ w/lib/matplotlib/text.py
@@ -363,6 +363,8 @@ class Text(Artist):
         """
         thisx, thisy = 0.0, 0.0
         lines = self._get_wrapped_text().split("\n")  # Ensures lines is not empty.
+        import sys
+        if lines == ["foo"] and sys._getframe().f_back.f_code.co_name != "draw": lines = ["a longer label"]
 
         ws = []
         hs = []

which results in
Figure_1
but obviously that is not a "practical" solution (even though I'm happy to have that in my toolbox).

Proposed solution

At least for mathtext strings, we could support the TeX macros \smash, \phantom, and their variants, which are the TeX approach for fixing such alignment problems (see e.g. https://www.tug.org/TUGboat/Articles/tb22-4/tb72perlS.pdf). It is not entirely optimal to only support this for mathtext strings, but that's the best I can think of right now -- adding an additional "faked_size" (or similar) property on Text objects seems less convenient, e.g. for the legend case above.

@timhoffm
Copy link
Member

Manipulating text metrics to monkey-patch layout is ok for TeX because basically all they have is text. But it feels much too specific for our case. I think we'd need more general tools to configure sizes and available space for Artists, likely something like Qt's sizeHint() / QSizePolicy mechanism.

If it's easy to support \smash / \phantom you can still do that as a particular feature of mathtext.

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

No branches or pull requests

2 participants